AirJD 焦点
AirJD

没有录音文件
00:00/00:00
加收藏

真有趣的游戏内存数据库实践报告面向游戏业务的内存数据库开发 by 陈明达@真有趣

发布者 devops
发布于 1473383182023  浏览 6133 关键词 NoSQL, 游戏, 数据库 
分享到

第1页

面向游戏业务的内存数据库开发

真有趣的游戏内存数据库实践报告



第2页

Copyright © 2016 SoFunny



第3页

正式开始之前

Copyright © 2016 SoFunny



第4页

自我介绍

• 陈明达,花名:达达 • 来自厦门真有趣信息科技有限公司 • C#、PHP、Erlang、Go、AS3 • 杂而不精,现学现卖,土法造炮

Copyright © 2016 SoFunny



第5页

今天主要的内容

• 游戏内存数据库方面的实践经验 • 游戏内存数据库的一些实现细节 • 供大家参考,希望大家可以少走弯路

Copyright © 2016 SoFunny



第6页

为什么讲内存数据库

• 因为它影响产品的方方面面 • 产品品质:游戏过程要流畅,游戏数据要安全 • 开发效率:开发要简单高效,不要很容易出BUG • 运维效率:运维方案要成熟可靠并且高效 • 运营效率:要方便数据挖掘 • 它的演进过程也是架构演进的缩影

Copyright © 2016 SoFunny



第7页

内存数据库的诞生过程

Copyright © 2016 SoFunny



第8页

第一次实践



• 《魔法之城》,SLG,2008年 • PHP + Memcached + MySQL • 手工编写数据库到缓存的加载代码 • 手工编写缓存到数据库的落地代码



PHP Memcached

MySQL



Copyright © 2016 SoFunny



第9页

第一次实践遇到的问题

• 手工做的事情太多,每一个业务都 是特例,缺乏强约束力的规范,导 致BUG频发

• 没有事务保护,业务上的BUG直接 导致数据损坏,手工修数据和排查 问题耗费大量精力

Copyright © 2016 SoFunny



第10页

迷茫阶段

• 怎样才能减少手工和特例化产生的BUG? • 怎么实现事务机制? • 怎么容灾? • 传统数据库还是KV数据库? • 是否有现成方案?

Copyright © 2016 SoFunny



第11页

理清思路

• 时间和能力有限,做最有把握做到的事 • 使用MySQL,运维方案成熟可靠,便于数据挖掘 • 自动映射MySQL表结构,规则简单,容易自动化 • 在游戏进程内组织数据,运行效率最高,容易实现

Copyright © 2016 SoFunny



第12页

第二次实践



• 《神仙道》,RPG,2010年 • Erlang + ETS + MySQL • 自动映射MySQL数据库结构 • 有事务机制 • 有SQL日志 • 有平滑升级机制



Erlang

业务逻辑



ETS



MySQL



SQL日志



Copyright © 2016 SoFunny



第13页

第二次实践遇到的问题

• 按表来组织缓存,数据集太大,游 戏越跑越慢(ID取模分表缓解)

• SQL文本日志文件不利于数据挖据

Copyright © 2016 SoFunny



第14页

第三次实践

• 《仙侠道》,RPG • Go + MySQL • 按玩家切分数据集 • 按业务切分数据集 • 结构化的事务日志 • 脚本化的审计工具

Copyright © 2016 SoFunny



Go

业务逻辑



Player DB



MySQL



事务日志



第15页

第三次实践遇到的问题

• 优化太早,引入不必要的复杂度 • 常驻内存,运营到后期硬件利用率降低 • 自定义二进制格式的事务日志不利于周边工具开发

Copyright © 2016 SoFunny



第16页

近期我们在做的

• 支持大服制游戏 • 冷数据剔除,提升硬件利用率 • JSON替代二进制,进一步发挥日志的价值 • 加入索引机制,允许后期优化,避免过早优化

Copyright © 2016 SoFunny



第17页

内存数据库的实现细节

Copyright © 2016 SoFunny



第18页

几个关键点

• 部署结构 • 平滑升级 • 数据切分 • 事务机制

Copyright © 2016 SoFunny



第19页

部署结构



• 游戏服和MySQL是多对一关系



1服 2服 3服



• 游戏启动时全量缓存数据 • 游戏数据变更异步回写MySQL • MySQL做主从同步



主库 从库



• 在从库上做完整备份+增量备份



完整



增量



运营



• 运营后台到从库查询数据



备份



备份



后台



Copyright © 2016 SoFunny



第20页

平滑升级

• 每次结版前都要手工收集数据库变更是很辛苦的,而 且容易犯错

• 从开发过程中就严格执行平滑升级过程,跨版本升级 只是重现开发过程

• 以日期+序号作为命名规则,每次数据库变更都提交一 份PHP脚本到一个固定目录下

• 用一个PHP脚本去顺序执行目录下的变更脚本,并记 录下当前版本

Copyright © 2016 SoFunny



第21页

按玩家切分数据

• 游戏业务的特性: • 玩家大部分时间都在操作自己数据 • 每个玩家的数据集并不大

• 按玩家切分数据会产生两种表: • 一对一,每个玩家只有一条数据,比如玩家信息 • 一对多,每个玩家有多条数据,比如物品

• 命名规则很重要: • 玩家表“player_”开头 • 一对一的表,用“pid”做主键 • 一对多的表,用“id”做主键,必须有“pid”字段

Copyright © 2016 SoFunny



第22页

按业务切分数据

• 全局数据,比如帮派: • 帮派成员,帮派公告,所有周边系统都是以帮派为单 位访问数据的,所以按帮派切分数据很合理

• 玩家数据进一步切分: • 装备强化,装备洗练,装备镶嵌,所有装备养成系统 都是以装备为单位访问数据的,所以可以在装备对象 上加上子表数据引用

• 如果可以建立完善的索引机制,没必要根据业务切分数据

Copyright © 2016 SoFunny



第23页

事务回滚

• 首先需要顺序记录下事务过程中的非查询操作 • 事务回滚的时候从最后一笔纪录往前回滚 • 如果是插入数据,就把新数据删除 • 如果是修改或删除,就把旧数据替换回去

Copyright © 2016 SoFunny



第24页

事务回滚–示例

Insert 1 Update 2 Update 3

Delete

Copyright © 2016 SoFunny





第25页

事务提交

• 我们已经有一份非查询操作记录 • 按这份记录顺序生成SQL同步到数据库即可 • 但是必须强调,要以事务为单位:

• SET autocommit=0; • START TRANSACTION; • COMMIT;

Copyright © 2016 SoFunny



第26页

事务日志

• 我们已经有一份非查询操作记录 • 按这份记录顺序写入日志文件即可 • 前面说到结构化的事务日志:

Copyright © 2016 SoFunny



第27页

事务隔离

• 并发操作数据的时候,如何做好事务隔离? • 最土的办法是不要并发,等价于MySQL的串行级别 • 串行为什么可行?

• 人可感受的延迟大约在100ms左右 • 平均每次请求处理耗时40us • 100ms足够执行2500个请求 • 利用多核?那就按玩家做事务隔离,但是互动要单独隔离

Copyright © 2016 SoFunny



第28页

Thanks



支持文件格式:*.pdf
上传最后阶段需要进行在线转换,可能需要1~2分钟,请耐心等待。