房间分片策略
概述
逻辑层要支撑更多房间,必须把房间分散到多个节点。房间分片解决"房间在哪"的问题:路由表负责把请求送到房间所在节点。分片策略的核心权衡是均衡性(热点倾斜)与伸缩性(节点增减时迁移量)。本文对比 Hash 分片与一致性哈希,并设计动态伸缩方案。
一、Hash 分片
1.1 取模分片
Hash 分片(取模):
node = roomId % N(N = 节点数)
优点:
实现简单、路由确定、无额外数据结构
缺点:
节点增减 → 全部房间重新映射(大规模迁移)
部分热点房间集中在某节点 → 不均衡// 取模路由
public int route(long roomId, int nodeCount) {
return (int) (roomId % nodeCount);
}1.2 适用场景
适用:
节点数稳定(长时间不扩容)
房间量大且分布均匀
简单架构(中小规模)
问题场景:
频繁加节点 → 每次全量迁移
热门玩法房间集中 → 热点节点过载二、一致性哈希
2.1 原理
一致性哈希(Ketama):
节点 hash 到环上(0-2^32)
房间 key hash → 环上顺时针找第一个节点
节点增减只影响相邻区间的映射(少量迁移)
虚拟节点:
每个物理节点映射多个虚拟节点(分散环上)
解决真实节点分布不均
虚拟节点数(如 160)影响均衡度// 一致性哈希路由(Ketama 算法示意)
public class ConsistentHashRouter {
private final TreeMap<Long, String> ring = new TreeMap<>();
public void addNode(String node, int vNodes) {
for (int i = 0; i < vNodes; i++) {
long hash = md5Hash(node + "#" + i);
ring.put(hash, node);
}
}
public String route(long roomId) {
long hash = md5Hash(roomId);
Map.Entry<Long, String> entry = ring.ceilingEntry(hash);
if (entry == null) entry = ring.firstEntry(); // 环回绕
return entry.getValue();
}
}2.2 对比
| 维度 | Hash 取模 | 一致性哈希 |
|---|---|---|
| 实现 | 简单 | 中等 |
| 节点增减迁移 | 全部 | 少量(约 1/N) |
| 均衡性 | 依赖 key 分布 | 虚拟节点均衡 |
| 热点处理 | 无 | 虚拟节点缓解 |
选型建议:
节点稳定、简单 → 取模
会频繁扩缩容 → 一致性哈希
房间有热点 → 一致性哈希 + 虚拟节点三、动态分片伸缩
3.1 扩容流程
扩容(加节点):
1. 新节点加入(注册路由表)
2. 计算需迁移的 shard/房间
3. 逐个迁移(快照 → 目标节点加载 → 切换路由)
4. 迁移完成确认 → 路由表更新
关键:迁移不打断对局
对局中房间延迟迁移(对局结束再迁)
或双活(新旧节点同时处理,切路由)缩容(减节点):
1. 标记节点下线(不再分配新房间)
2. 存量房间迁移到其他节点
3. 全部迁完后节点下线3.2 迁移协议
迁移步骤(房间):
1. 源节点:冻结房间(暂停新操作)→ 导快照
2. 目标节点:创建房间 → 加载快照 → 接管
3. 切换路由:后续请求走新节点
4. 确认迁移成功 → 源节点释放
一致性:
迁移期间新消息缓冲(旧节点)或重定向
快照丢失 → 从持久化恢复(快照兜底)// 迁移控制消息
MigrateRoomMsg(roomId, snapshot) // 源 → 目标
RoomMigratedAck(roomId) // 目标 → 源
RouteSwitchMsg(roomId, newNode) // 更新路由表3.3 自动伸缩
自动伸缩(按负载):
监控节点负载(CPU/房间数/QPS)
过载 → 触发扩容/迁移
空闲 → 触发缩容
考虑:
自动伸缩有抖动风险(频繁开关)
建议:半自动(告警 + 人工确认)
迁移成本高 → 触发阈值保守四、分片管理实现
4.1 路由表
路由表存储:
全量路由表(roomId → node)→ 一致性哈希可计算,不需存表
或动态映射表(Redis/配置中心)→ 灵活但需一致
推荐:
一致性哈希(可计算)为主
特殊映射(强制指定节点)覆盖
路由一致:
所有节点同一路由算法
变更时同步(广播/配置中心)4.2 热点处理
热点房间对策:
热门房间拆分为多个实体(分区玩法)
或单独部署热门房间(大房间独立节点)
限制单房间容量(玩家数上限)
监控热点房间,必要时迁移五、实现要点
设计清单:
节点稳定 → 取模;频繁伸缩 → 一致性哈希
虚拟节点保证均衡
迁移协议(快照 + 路由切换 + 确认)
迁移不打断对局(延迟迁移/双活)
路由表全局一致(配置中心同步)工程注意:
迁移失败重试(幂等)
迁移中消息处理策略
监控(分片分布/迁移状态/负载)
机房/多活考虑(就近路由)常见坑:
取模扩容全量迁移 → 一致性哈希
热点房间拖垮节点 → 拆分/独立部署
迁移丢状态 → 快照 + 持久化兜底
路由不一致 → 双写期间读旧节点与其他系统衔接:
路由 → 网关转发章节
Actor 分片 → Akka Cluster 章节
快照 → 持久化/Event Sourcing 章节
负载监控 → 性能监控章节