游戏不好搞啊,设计的东西,能尽量简单就简单,代码太多判断就写死行了,反正它运行起来是对的就行了。

情形:09:00

昨天发生了很痛苦的一件事情,那就是游戏中data内存同步不到data数据库,这个问题在第二天才发现(游戏还可以正常玩),这让人很担心啊。同步data内存的是一个定时器TaskTimer,这个定时器会定时回写数据到data库中,但在某个时间点后就发现数据库没有增,一直停留停在那个点上;看到这个问题时,游戏肯定是不允许kill掉重启的(部分玩家数据会没有,会回档)。

确认问题:18:00

一开始时,就以为是后台操作不对,或配置有问题会导致data同步TaskTimer停掉,但开服后过一段时间才是这样,TaskTimer停掉的时候管理员也没有做不当的操作,所以查找操作日志是否恰当,查找配置是否有问题,查找数据库的密码是否被改过,查找代码是否有问题等,排除了外部的问题后,觉得是底层代码有问题,于是看了同步内存的代码,逻辑上是没有什么问题的,以前也没有出现过这种问题(开过好多个服),也是只之前的运气好,呵呵,其中发现在save(保存)操作时是没有try catch是,如果save有超时,过多操作等问题这里可能会报错。其中save方法里没有throw Error,但我们还是相信是这里出了问题。

想出解决办法:21:00

随着玩家数的增加,充值的增加,也意味着要快点解决问题,或则没有办法同步数据则丢失数据更严重。于是查看了游戏重启接口,这里是当游戏停服时,会停掉外网玩家的请求,将内存数据立即写入数据库,完成后会调用sh脚本kill me 再启动游戏。但同步内存代码和重启同步是同一个方法(同一个代码),痛苦啊。。。。定时器挂掉也是这段代码,虽然我们觉得是save有报错而停掉,如果不是,重启还是一样保存不了,那更惨。。。又认真研究这些代码,save报错的可能性最大,第二可能性是数据库操作对象无郊了,于是将目光转移到数据库操作对象这里,这个对象重启时会不会有问题呢?后来发现在重启时,是new 一个同步对象出来的,同步把新的数据库连接对象放入进去(很好的设计)。 于是我们就不担心数据库操作对象的问题了,这是方案一;如果方案一失败后,就直接导致无法恢复,这也是不允许的(除非逼不得已),于是有了方案二(备用方案,将损失降到最低),该方案是模拟现在所有的玩家,去登录外网服,然后请求能用于用户数据恢复的接口,将获得的数据,再一步步解析出来,用这些数据去还原一个玩家的重要数据,这也就相当于做前端了,比如:获得用户的等级level,则记录下来,再自己去new 一个User到自己数据库保存好。方案二也是逼不得已的,方案二的可行性及实现性很低,完全恢复也不是可能的,数据大多,并且工作量巨大。但不能丢掉数据,唉,方案一一旦执行后,则无法执行方案二,所以只能去试试方案二了。

实现方案:00:00

一开始方案二无从下手,要获得一个完整的玩家数据,则要从多个接口去获得,并且写的时候还不能直接去测试(会对外网玩家有很大的影响),只能将备份外网的数据库过来测。这些数据是正确的,但data库中(有三个库)数据不全(在内存中),这三个库如果是正常测试的话,数据是要一一对应的。所以蛋痛啊。。。。这叫我怎么去写代码拿数据,几个小时后还是没有办法写出代码来,估计是一辈子要写最凄凉的代码了。。。

最终执行:04:50

方案二明显是不可能做到的,于是放弃了,也是没有办法的了,所以将目光转向到方案一,方案一是重启,但又不想让程序停掉,所以我们将kill的脚本给删除了,到时重启时程序无法找到脚本从而无法重启,这时我们又可以多测试几次执行将内存同步数据库的代码,这恐怖的代码,让我们还是不放心,于是就在内网做定时器的异常报错,重启时再跑那些代码,内网测试是能同步内存的。所以现在将内存同步代码try catch 多写个可以控制游戏内存同步数据库的代替接口,将该版本更新到外网(重启后生效)。

最终结果:5:30

成功!再进入游戏测试,结果数据都同步到了数据。。。这天都不知道死了多少脑细胞。。。。。

 

【总结】

1、如标题:能尽量用数据库代替内存就用吧,减少整天担心内存问题----内存确实是能带来读取数据的方便与快,但管理内存却是一件很头痛的事情,也很容易失去数据,所以效率允许的情况下,你还是改用数据库吧,毕竟--安全,稳定之后 才是效率

2、多写容错结构,像重启时执行代码对象里,是重新分配一个新的数据库操作对象过来,如是还是用旧的那个,之前别的地方用它挂掉了,那其他重要的执行则无法执行了。

3、相信自己的眼光,不要过多的猜想,运行好久的底层代码也是不可靠的

 

 

 

posted on 2013-04-20 13:21  HolleHuang  阅读(2182)  评论(7编辑  收藏  举报