最近组内发表一篇小论文,是关于改进游戏储存系统的IO性能思路。老大原来早有相同的想法,并且已经实现了大部分模块,后来和老大一同努力,新的储存引擎终于逐步完善。在外服环境跑了两个多月,性能和可靠性得到了明显的提升。具体的细节就不方便发表了,实践证明,用binlog来做MMORPG的数据储存是行得通的。
几个事实:
1. 磁盘IO的瓶颈在寻道,顺序写性能比随机写性能高一个数量级。
目前典型硬盘的顺序写入速度大约是60MB/s , 而寻道时间在5~8ms (200次/秒)。可以看到硬盘IO的主要瓶颈在于磁头寻道,也就是随机写。在linux开发服(非虚拟机,Xeon 3.0G 4核/16G内存)上做了一个benchmark。
顺序写50MB: 700ms
写5000个文件,每个10KB(共50MB): 12秒
10000次随机写,每次1KB(共10MB): 21秒
2. 游戏数据都是K-V数据,关系查询需求极少;k-v数据的update很频繁(实测是每玩家每5秒一次修改)
3. MMORPG单服的玩家同时在线数量是10K级别, 这个数量级可以有效估算binlog的规模,使得方案可行。
一般MMORPG系统的存盘策略: 定时存盘。就是过一段时间(比如5分钟)把在线有修改过的玩家数据,整个snapshot存下去(mysql也好,文件系统也好)。这样有两个主要问题:一到保存点,IO随机写暴增,玩家卡机;如果系统down机, 数据就会有几分钟的回档。而性能和数据可靠性两则是矛盾的,存盘间隔过小,玩家卡机,过大,故障后数据回档时间长。需知现在的MMORPG,贵价武器价值都成千上万RMB,数据可靠性对游戏营运影响还是很大的。
so, 可以用定制的binlog来记录玩家数据,也就是说,不记录整个snapshot,而是每个k-v变化时记录opcode马上写入binlog文件, binlog的格式根据游戏情况可以高度定制,尽量减少空间。由于是顺序写,性能可以非常高。如果down机,可以根据binlog来恢复,基本上没有回档。不过要解决一个问题:binlog增长过大 --> 崩溃恢复时间过程 & binlog文件本身损坏的风险增大 & 磁盘空间用光。因此binlog需要有rotate机制, rotate的时候需要存一次在线玩家数据的snapshot, 这样旧的binlog就可以存到远处或者丢弃。rotate的过程中需要考虑恢复时玩家数据一致性和完备性等等一系列细节问题,后来一一解决了。
这是最近做的成就感的事。几年没写blog了,笔记都记在evernote里,最近又想在公开的地方写点东西,发个文纪念一下。