数码鹭岛论坛
标题:
游戏数据存储方案?
[打印本页]
作者:
翔子
时间:
2014-8-28 10:54
标题:
游戏数据存储方案?
原文: http://www.zhihu.com/question/24983647
同时更改记录A和记录B,如何保证数据一致性落地。
大家都有什么存储方案呢? nosql的也可以。
目前的思路,相对逻辑代码比较复杂不可控。
mysql:
1、启动事务
2、内存变更
3、提交到数据库,等待回调
4、回调:
成功:处理业务
失败:回滚,重置内存数据
-------------
达达,服务端程序员,主页:http://1234n.com
沈晟、lantaozi、王延 等人赞同
谢邀。
我目前用的就是类似你说的这个方式。
请求到达 -> 解包 -> 启动内存数据库事务 -> 请求路由给对应功能模块 -> 执行业务逻辑 -> (接下来,两种可能):
1. 正常处理完请求 -> 提交内存数据库事务-> 内存数据库事务写入事务日志 -> 内存数据库事务转成数据库事务执行
2. 非法请求或程序BUG -> 抛出异常 -> 内存数据库事务回滚
内存数据库事务转数据库事务我试过两种方式:
1. 动态组装SQL并执行
2. 用预先prepare好的语句绑定参数执行
两种都可以,prepare好处就是不需要动态拼接SQL,游戏端这边省内存又省CPU,MySQL那边也省CPU,但是update语句不是动态拼接SQL,要预先prepare语句只能全量更新,之前有担心效率不行,还好实际运行起来感觉没啥问题。不过prepare语句有一个数量限制,小心别被坑了就是。
我使用MySQL,所以事先要将MySQL的自动事务提交禁用,改用手工提交事务,否则可能出现同步一半的时候同步程序自身异常导致内存数据库事务只提交一半到MySQL得情况。
内存数据库的事务日志是非常重要的,写入MySQL之前需要先写同步日志,这样可以在MySQL通信故障时有数据可以还原,不用担心写日志的IO,顺序写入的效率是很好的,绝对没大负担。
另外我在同步日志里记录了完整新旧数据和请求的类型、玩家ID、事务执行时间,记录的格式是自定义的二进制文件格式,每个文件头部有完整的表结构信息,可以用一个对应的分析工具结合lua脚本来分析玩家行为,回查漏洞或者BUG。
也可以从同步日志截取生成完整的同步用的SQL或者回滚某段时间数据变化的SQL。
生成SQL逻辑很简单,UPDATE和DELETE不需要特殊处理,INSERT用REPLACE语法替代就可以让SQL反复执行,不需要人工精确对比。
内存数据库因为是自己实现的,所以要实现事务机制没有多复杂,插入的反操作就是删除、删除的反操作就是插入、修改的反操作还是修改。只要把新旧数据记录下来,要做事务回滚很容易。
内存数据库的代码是按MySQL数据库结构自动映射生成的,所以只需要设计好底层结构,开发人员不需要管这些底层的机制,只需要按功能设计数据库结构就可以了。
欢迎光临 数码鹭岛论坛 (http://www.clore.net/forum/)
Powered by Discuz! X3.2