我花了三天、跑了数百项验证,最后却没有打开新版存档
6 小时前34 浏览
这几天给游戏的存档系统做了一次比较彻底的重构。
最后的结果有点反常识:新系统的本地回归、隔离环境验证、旧档保护验证和正式启动验证都过了;但正式生产仍然维持旧版存档,新版存档继续关闭。
不是因为新系统没做完,恰恰是因为做完以后,才更清楚“能跑”和“能接管玩家数据”之间差得很远。
这篇不贴代码,不公开具体协议、云端命名、迁移规则或测试细节。只想把这三天里最值得记住的几个感受写下来。
- 最难的不是 Save 和 Load,而是什么时候该相信数据
刚开始做存档,很容易把它理解成一套很直白的流程:把数据存进去,再读回来。
真正麻烦的是,游戏并不只活在一次正常启动和一次正常退出里。它会切后台,会断网,会收到晚到的异步回调,会在写入完成前崩溃,也会在奖励已经算进内存、但还没真正成为持久事实时被系统杀掉。
现在看到的这份数据,到底有没有资格被当成事实?
内存里看起来已经完成的状态,不等于下次启动时也应该相信它。一次旧请求晚到的结果,也不该覆盖已经进入下一阶段的新流程。一个看似合理的离线区间,如果时间来源不可靠,也不该直接变成奖励。
后来我们把很多设计讨论都收敛到同一个问题:谁是当前可信来源,什么证据足以让流程继续,以及证据不足时系统应该做什么。
答案往往不酷:停下来,不迁移,不结算,不覆盖,等待新的证据。
- 新系统先学会“不接管”,再谈“接管”
这次最重要的决定,是不让新版存档直接替换旧版。
正式玩家仍然从原来的入口启动,仍然读写原来的存档版本。新版能力默认关闭,所有真实读写验证都先放在隔离环境里完成。即使隔离环境已经验证通过,也不意味着应该立即碰正式玩家数据。
这一阶段的验收没有只跑一份测试,而是分阶段做了数百项回归、隔离环境真实读写、旧档保护和正式启动验证,结果均通过。
Production Save = V4
Formal V5 = OFF
有人会问:既然都过了,为什么不开?
因为测试通过证明的是“在已知条件下,系统按预期工作”;接管真实玩家数据意味着要承担未知条件下的后果。这两件事不是同一个授权等级。
对存档来说,保守不是效率低,而是一种功能。
- 离线收益最危险的部分,不只是玩家改时间“
不要信本地时间”大家都知道。但做下来才发现,更麻烦的其实是异步结果本身也会过期。
想象一下:第一次时间请求发出后,玩家已经切换了状态;第二次流程开始了;这时第一次请求才回来。如果系统只看“这次请求成功了”,旧结果就可能污染新流程。
所以时间服务不是重点,重点是每一个异步结果都要能证明:它还属于当前这一次流程。
这件事同样适用于云存档读取、写入确认、前后台切换、恢复回调。它们看起来是不同问题,底层其实很像:旧消息不能替新世界做决定。
- 崩溃恢复只能相信已经落下来的东西
存档系统里最容易自欺欺人的状态,是“我刚刚已经处理完了”。
如果这个“处理完”只存在于内存里,崩溃一次以后它就没有发生过。恢复流程不能根据上一次运行时的主观印象继续走,只能从已经确认的持久数据重新判断。
尤其是离线奖励、迁移和关键写入这些流程,不能只用一个“已完成”状态概括。运行时进展、异步请求和已经确认的持久事实,需要被明确区分。否则某个很小的窗口,就可能在重启后变成重复奖励、旧数据回写,或者状态卡死。
很多代码在正常流程里都能跑得很好。真正拉开差距的,是它在最不合时宜的崩溃点能不能收敛回来。
- 我现在不太相信控制台最后那句 PASS 了
这次还有一个很朴素的教训:验收结论不能只看屏幕上的最后一行。
最后收口时,我们甚至遇到过一次很别扭的情况:测试结果本身已经通过,但报告里的一个执行状态与最终归档证据对不上。
如果当时只相信“我记得这轮已经 PASS”,这处矛盾大概率就会被带进最终结论。我们最后重新沿着原始输出、配置快照、执行状态和文件校验追了一遍,确认只是文档勘误,而不是系统异常。
但这件小事让我意识到,验收包不是流程装饰。真正需要交付的不只是“测试过了”,还应该包括:当前入口是什么、生产配置是什么、跑的是哪一版、日志来自哪次运行、文件是否能核对。
只有证据链闭合,PASS 才有意义。
- 写测试时,别只盯着模块边界
单个模块做得对,不代表组合起来也对。
最容易出问题的,往往是两个“各自都没错”的流程刚好交错:一个恢复还没结束,新的后台事件又来了;一次写入还在等确认,运行时状态已经继续变化;测试入口切走以后,正式入口忘了切回来。
所以这轮验收没有只跑某一个测试文件,而是分层确认:本地完整回归、隔离环境真实读写、旧版存档保护、正式入口启动和云档加载。每一层都在回答不同的问题。
我现在越来越觉得,测试不是为了证明系统永远不会出错,而是为了尽量提前知道:它会在什么情况下拒绝继续做错事。
- 最后
这三天没有让新版存档上线,但我觉得它完成了更重要的一步:新系统已经知道,在信息不够的时候,自己没有资格替玩家做决定。
以后真正开启新版存档时,仍然会是一次单独的授权、单独的验证,而不是“反正之前都测过了”。
这篇刻意没有展开具体的迁移协议、恢复链、可信源选择、异常判定和完整测试矩阵。那些内容决定的是系统怎么实现;这里更想分享的是,设计这类系统时应该先问哪些问题。
如果你也在做放置、养成、RPG,或者任何带离线收益和云档的游戏,可能最值得先补的不是一个更复杂的存档格式,而是这一句:
当证据不足时,系统应该停在哪里?
这个问题想清楚,很多后面看似随机的存档事故,其实会在设计阶段就露出形状。


