玩家回档原因分析
在最近一次维护后,玩家发现有较大规模的数据回档,还有一小部分玩家无法登录。现在尝试还原一下现场。
当天维护的时候,SA 执行了一次数据库维护。维护是通过一个脚本完成的,而且执行过多次,理论上没有问题。而维护的过程中,开发组这边需要执行一个脚本,给一批玩家增加经验。这一切完成后,QC 简单复测了一下,就开服了。开服后发现,服务器出现大量报错,而且都是玩家数据出现问题。定位这个问题的时候,发现玩家的数据丢掉了导致无法登录,顿时吓尿了 =_= | 论坛里也有玩家开始叫骂,定位了一下貌似是那批增加经验的玩家,于是马上复查增加经验的脚本。玩家数据存储是使用 redis 数据库的,脚本里就使用了一条 hincrby 指令,不应该会清掉数据啊 |
接着,我们想到了一个可能,会不会是 SA 做迁移的过程中,我们跑脚本了,然后迁移数据的脚本看见有数据,就不再存入,导致玩家数据只剩下刷入的经验值呢?实践出真知,实验表明,redis 自身是有实现保护的,正在恢复数据库的过程里,外部复写的数据会提示报错。虽然没追踪到主因,但是我们之前额外做了一套旁路备份,用 golang+leveldb 实现的一套 redis 存盘代码。里面的数据肯定是对的,只是由于 redis 对应 uid 里有数据,所以不再从 leveldb 里取数据而已。说时迟那时快,快刀斩乱麻将加经验那批玩家的 redis 数据干掉,玩家就可以登录了。
慢着,报错还是没有停,还有一大票玩家遇到同样的情况。我们终于开始怀疑 SA 同学的脚本了。后来才发现,由于之前没有规范操作,导致备份的目录错了,SA 同学启用的数据库位置是正确的,但是之前错误操作,把一个老的数据库放进正确的位置了,导致实际上跑起来的,是一个 147 天前的数据库。于是,加经验的那批玩家中,是这三个多月里创号的,就会只剩下一个刷入的经验值,建筑数据等等都会丢掉了。而没有刷入经验值的玩家,是通过 leveldb,取到最新的档案,所以反而能够正常游戏。
最终,在 2130 这个高峰时间,我们停服维护了。把下午维护前备份的数据库恢复回去,少部分玩家丢失了 3 个小时左右的游戏数据,so sad。事实证明,我们的旁路备份是坚实有效的,前提是修复故障前,先要理清头绪,不要盲目修复,才能最大限度的减少损失。另外,不要设定不可能区域,SA 同学也是人,也有犯错的可能。
Tag:
python