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

Q28: 如何解决数据一致性问题?

核心结论

在线游戏里谈一致性,不能空泛地只讲分布式事务。更有用的做法是先问:

  • 哪些数据必须强一致
  • 哪些数据允许短时间延迟一致
  • 哪些操作可以靠幂等和补偿解决

真正的工程方案通常不是“一套事务打天下”,而是按数据价值和业务后果分层处理。

一、先明确一致性问题发生在哪

常见来源包括:

  • 并发更新同一份数据
  • 多服务分别持有局部状态
  • 缓存与数据库先后不一致
  • 重试导致重复执行
  • 跨服或异步链路出现部分成功

所以一致性问题不只是数据库事务问题,也是系统边界问题。

二、哪些场景必须更强一致

通常包括:

  • 货币和资产
  • 交易
  • 拍卖成交
  • 邮件附件领取
  • 充值到账

这些链路一旦错,不只是数值抖动,而是直接影响用户资产和对账。

更常见的做法是:

  • 单权威写入
  • 幂等操作 ID
  • 可靠落库
  • 审计流水

三、哪些场景可以接受最终一致

例如:

  • 排行榜展示
  • 好友在线状态
  • 世界公告分发
  • 某些缓存视图

这类数据允许短时间延迟,只要最终收敛即可。

关键是不要把它们错误地塞进重事务链路。

四、解决一致性的几种常见手段

1. 单写者模型

很多游戏系统会让某类数据始终由唯一权威节点修改。

好处是:

  • 并发冲突少
  • 逻辑清晰
  • 不需要大范围锁

这在玩家实体、场景实体、背包主对象里非常常见。

2. 数据库事务

本地事务适合单库内的强一致修改,例如:

  • 扣钱加道具
  • 邮件状态加附件领取标记

但前提是操作边界清晰,且不要把事务拉得过大。

3. 幂等

只要链路存在超时、重试、补偿,就必须有幂等能力。

典型做法:

  • 业务唯一 ID
  • 去重表
  • 唯一约束
  • 重复请求返回旧结果

4. 事件和补偿

跨服务链路里,很多时候比强行做分布式事务更现实的是:

  • 明确主操作
  • 记录事件
  • 下游异步消费
  • 出错时做补偿或重放

五、不要滥用分布式事务

在线游戏不是不能做分布式事务,而是很多链路并不适合。

原因包括:

  • 调用链长
  • 延迟敏感
  • 节点波动常见
  • 回滚语义复杂

在很多业务里,单权威加幂等加流水,比 2PC 更可维护。

六、缓存一致性怎么处理

缓存一致性是最常见的实际问题之一。

常见策略有:

  • 先写库再删缓存
  • 由权威节点负责更新缓存
  • 对热点数据设置短 TTL
  • 关键链路避免多处可写缓存

重点是减少多写入口,而不是幻想缓存永远和数据库完全同步。

七、工程上更稳妥的组合

很多系统最后会收敛到:

  • 资产类操作:单权威写入加本地事务加流水
  • 跨服务更新:事件驱动加幂等消费
  • 展示型数据:允许最终一致
  • 缓存:作为加速层,不作为唯一真实来源

这比“一切都强一致”更现实。

八、常见误区

1. 一致性问题就是数据库隔离级别问题

远远不止。很多错误来自重试、缓存、异步消费和多服务写入。

2. 只要用了事务就不会错

事务只能覆盖它所在的数据边界,跨服务、跨缓存、跨队列的问题还在。

3. 所有数据都应该追求强一致

代价通常太高,而且很多展示数据并不值得。

参考资料

  • 各类在线游戏资产链路、幂等与补偿设计实践资料
在 GitHub 上编辑此页
最后更新: 3/20/26, 6:06 AM
贡献者: cuihairu