Apollo 技术文档Apollo 技术文档
指南
  • 架构概述
  • BigWorld 架构深度解析
  • BigWorld 进程架构与玩家生命周期
  • AOI九宫格系统详解
  • AOI广播与消息去重
  • Base 模块
  • Core 模块
  • Runtime 模块
  • Data 模块
  • Network 模块
  • /modules/actor.html
  • Game 模块
  • BigWorld 模块
服务器应用
API 参考
QA
GitHub
指南
  • 架构概述
  • BigWorld 架构深度解析
  • BigWorld 进程架构与玩家生命周期
  • AOI九宫格系统详解
  • AOI广播与消息去重
  • Base 模块
  • Core 模块
  • Runtime 模块
  • Data 模块
  • Network 模块
  • /modules/actor.html
  • Game 模块
  • BigWorld 模块
服务器应用
API 参考
QA
GitHub
  • MMORPG 架构 QA

Q35: 如何实现数据库分片?

核心结论

分片不是为了“显得架构高级”,而是当单库在容量、吞吐、维护窗口或故障域上已经撑不住时,才需要把数据拆开。

真正重要的不是分成多少片,而是先回答:

  • 为什么要分
  • 按什么键分
  • 以后怎么扩容
  • 跨片查询和跨片事务怎么收敛

如果这些问题没想清楚,分片只会把问题从一个库复制成很多库。

一、先判断是不是真的需要分片

很多系统在真正分片前,往往还有更便宜的手段:

  • 索引优化
  • 读写分离
  • 冷热分层
  • 归档历史数据
  • 缓存热点数据

如果这些都没做,过早分片通常只会增加复杂度。

二、最常见的两类拆分

1. 水平拆分

把同类数据按行分到不同库或表里。

常见于:

  • 玩家主档
  • 背包
  • 邮件
  • 日志流水

2. 垂直拆分

把不同业务模块拆到不同库。

例如:

  • 账号库
  • 角色主档库
  • 社交库
  • 拍卖库

这更像按业务边界拆,而不是按数据量拆。

三、分片键怎么选最重要

分片键决定了:

  • 数据分布是否均匀
  • 查询是否容易路由
  • 扩容是否容易

在线游戏里常见分片键包括:

  • player_id
  • account_id
  • server_id
  • 时间维度

但没有万能键,关键看业务访问模式。

例如日志很适合按时间拆,角色主档更适合按角色或账号拆。

四、分片最怕什么

最怕的是查询和事务模型与分片键不匹配。

常见代价包括:

  • 跨片聚合变重
  • 跨片事务复杂
  • 扩容迁移困难
  • 热点集中到少数分片

所以分片键不能只看“好算”,还要看“以后怎么查、怎么迁、怎么扩”。

五、扩容要在第一天就想好

很多系统第一次分片能跑,但第二次扩容就开始痛。

需要提前考虑:

  • 分片数是否可扩
  • 新旧分片如何迁移
  • 路由规则如何升级
  • 历史数据是否回迁

一致性哈希、逻辑分片号、路由层抽象,都是为后续扩容服务的。

六、跨片事务不要轻易美化

一旦跨片写入变多,系统复杂度会明显上升。

更务实的做法通常是:

  • 让同一业务对象尽量落在同一片
  • 关键链路减少跨片事务
  • 必要时用幂等和补偿

而不是一开始就把所有跨片一致性都压给分布式事务。

七、在线游戏里更现实的分片思路

很多时候会采用组合方式:

  • 玩家主数据按 player_id 拆
  • 日志与流水按时间拆
  • 跨服数据按 server_id 或大区拆
  • 高价值模块单独成库

这比强行一套规则覆盖所有表更实际。

八、常见误区

1. 分片就是取模

取模只是最简单路由方式,不等于完整分片方案。

2. 先分 64 片以后就省心

不对。过多空片和不合理路由同样会带来运维成本。

3. 分片后性能问题自然消失

热点、不合理查询、跨片聚合仍然可能把系统拖垮。

参考资料

  • 各类在线游戏分库分表与按时间归档实践资料
在 GitHub 上编辑此页
最后更新: 3/20/26, 6:06 AM
贡献者: cuihairu