Daly的游戏人生

基于binlog的游戏数据储存引擎

    最近组内发表一篇小论文,是关于改进游戏储存系统的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里,最近又想在公开的地方写点东西,发个文纪念一下。


posted on 2012-07-01 18:05 Daly 阅读(1810) 评论(6)  编辑 收藏 引用 所属分类: 游戏开发

评论

# re: 基于binlog的游戏数据储存引擎 2012-07-02 09:08 zuhd

能详细说下binlog的几个缺陷吗?  回复  更多评论   

# re: 基于binlog的游戏数据储存引擎 2012-07-02 12:39 Daly

@zuhd

其实snapshot的保存还是需要的,只是用来binlog可以大大延长存盘间隔。
主要缺陷是:
1. 如果热数据很多,并且很频繁。binlog文件增长非常快, 硬盘很容易吃满. 对于热数据量大的项目不合适

2. 要勾住项目里的k-v变化, 对引用型的复杂类型(map或list),有可能会漏掉。如果代码里的k-v set都是用统一接口,则问题不大。

3. 要对复杂类型(map或list)的改变定义opcode比较难,要依赖于具体数据意义做opcode的定义,不然要整个map给dump下去,太耗了。

4. 这个binlog系统的opcode由于是高度定制,不同项目间不具有移植性。

5. 写log一般是单独的线程或进程,要注意数据一致性等等细节,要详细验证。  回复  更多评论   

# re: 基于binlog的游戏数据储存引擎 2012-07-02 12:43 Daly

@zuhd

当数据变化写binlog的顺序IO大到一定程度,则系统性能更糟糕(就是diff的数据量大于数据snapshot本身), 这个做法就不适合。所以要考虑数据规模,数据变化频率等因素。  回复  更多评论   

# re: 基于binlog的游戏数据储存引擎 2012-07-17 22:12 liutp

做个存储服务进程 应该就可以  回复  更多评论   

# re: 基于binlog的游戏数据储存引擎 2012-08-25 22:03 ZealotYin

我可不可以这样理解,你们游戏行业的数据基本都是全基于内存和DB的,你们需要定时给用户设置一个存档点(将某个时间的用户数据存盘),传统的操作是只使用snapshot来实现,而你们是使用定期(较长时间)snapshot加binlog的方式.这样可以减少做snapshot的次数,提高性能.对吗?
抱歉,我是非游戏行业的,所以您的应用场景有点看不懂,但是我专注于存储.所以以后有机会可以多交流一下。我新浪微博ID:殷伟雄  回复  更多评论   

# re: 基于binlog的游戏数据储存引擎 2012-12-07 16:41 Daly

@ZealotYin
嗯,是这个意思。另外两次snapshot保存之间如果crash会丢数据,binlog可以保证恢复。  回复  更多评论   


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理