Q26: 玩家数据什么时候存数据库?全量保存 vs 增量保存?
核心结论
玩家数据落库不是“越勤越安全”,也不是“攒久一点更省库”。正确做法通常是分层保存:
- 关键资产和关键状态及时落库
- 普通状态用脏标记加批量刷盘
- 可重建的临时状态尽量不直接持久化
全量保存实现简单但写放大明显,增量保存效率更高但复杂度更高。多数在线游戏最终采用的是混合策略,而不是二选一。
一、先区分哪些数据值得立即保存
并不是所有玩家数据都应该同一时机落库。
通常可以分成三类:
1. 高价值数据
例如:
- 货币
- 道具
- 邮件附件领取
- 交易结果
- 充值和发奖
这类数据要优先保证正确性,通常要么立即落库,要么进入可靠持久化流水。
2. 中价值数据
例如:
- 任务进度
- 技能等级
- 装备强化结果
这类数据常用脏标记和短周期批量保存。
3. 低价值或可重建数据
例如:
- 临时坐标
- AOI 内对象缓存
- UI 状态
- 某些临时 Buff 表现层信息
这类数据没必要每次变化都落库。
二、什么时候保存更合理
常见保存时机通常组合使用。
1. 关键事件后保存
适合:
- 获得或消耗资产
- 完成关键任务
- 拍卖成交
- 邮件领奖
这是最需要稳的保存点。
2. 周期性批量保存
适合:
- 角色成长状态
- 非关键进度
- 普通属性
优点是能平滑数据库压力,缺点是服务异常时可能丢失最近一小段变更。
3. 下线或切场景保存
适合做一次补充型落库,但不适合把它当成唯一保存时机。
原因很简单:
- 崩溃时可能来不及
- 移动网络环境下断线不可靠
- 玩家可能长时间不下线
4. 服务关闭前刷盘
这是兜底手段,不是主保存策略。
三、全量保存和增量保存怎么选
1. 全量保存
全量保存的特点是:
- 实现简单
- 序列化边界清晰
- 恢复容易
问题也很明显:
- 写放大严重
- 无关字段也会频繁刷库
- 热门角色或高活跃玩家成本很高
它适合:
- 数据量不大
- 团队规模较小
- 原型期或早期版本
2. 增量保存
增量保存只写变化字段或变化子对象。
优点:
- 减少写流量
- 更适合高频变更
- 更容易按模块拆分
问题:
- 脏标记维护复杂
- 恢复链路更容易出错
- 容易出现部分状态遗漏
它更适合数据规模大、在线高、对象复杂的系统。
四、为什么多数项目最后会走混合方案
因为不同模块最优策略不同。
典型组合是:
- 角色主档定期全量快照
- 背包、货币、邮件、交易做增量或事件落库
- 日志和流水单独写入
- 可重建临时态不直接入库
这样做的价值是:
- 快照便于恢复
- 增量降低写放大
- 流水便于审计和补偿
五、只靠主表保存为什么不够
高价值系统通常不能只靠一份“当前状态表”。
例如货币变动,更稳妥的做法通常是:
- 更新当前余额
- 记录变动流水
- 关键链路具备幂等 ID
否则出现误写、重试或补偿时,很难追查。
六、工程上更稳妥的保存体系
一个常见做法是:
- 内存中维护权威对象
- 对象字段使用脏标记
- 周期任务批量刷普通脏数据
- 关键资产操作立即提交或写可靠队列
- 定期输出角色全量快照
- 关键行为保留审计流水
这样既能控制数据库压力,也更容易恢复和对账。
七、常见误区
1. 所有变化立即写库最安全
这会把数据库变成实时状态机,吞吐和抖动都很难控制。
2. 只要定时保存就够了
对资产类操作通常不够,异常时损失可能无法接受。
3. 只做全量保存最简单所以最好
简单不等于长期可扩展。在线量和对象复杂度上来后,写放大会很明显。
参考资料
- 各类在线游戏角色持久化与审计流水实践资料
