不同服务器之间的数据同步(skynet 和 c++)

需求分析

最近公司开发了一个捕鱼游戏,现在想要把这个项目嵌入到公司已有的游戏中,成为其子游戏,开发捕鱼的服务器框架是基于 skynet 的框架(独立一套系统)。而已有的游戏服务器框架是c++自研框架(也是独立的一套系统),所以需要解决一个问题:就是两个系统中数据共享的问题,因为用户都是现有游戏中的。捕鱼并没有用户,用户从主游戏中进入到捕鱼势必要把 ta 的金币、钻石、道具等数据带到捕鱼服务器,最终用户退出捕鱼游戏,要把用户现在的金币和其他数据移动回去,这里就涉及到数据共享和维护数据唯一性的问题了。

最初的方案是选择 http 请求通知的方式进行通信。但是考虑到极端情况: 如高并发,如果一秒钟发起 2W 次请求那么以 http 的处理方式就是要 每秒建立tcp链接和断开链接 * 2W次,文件描述符占用、和不能便捷集成到两个系统业务层中、以及网络异常处理需要依赖到DB保存数据待后续恢复、以及后续的集群部署需要再做考虑,等等这些缺点都是无法忍受的。

后面考虑用 redis 的 Pub/Sub 来实现高效的 MQ 并且在请求发起的时候如果超时,如果数据是必须被对方接收的话,还可以直接把数据写入缓存,让对端自行获取。遂和其他 xxMQ 进行对比,最后不管从易用性、通用性、高可用等等方面上都是 redis 胜出,当然 redis 的 Pub/Sub 也是有缺点的,但是使用到上述的这个应用场景来说,都是可以忽略的。

数据一致性保证机制
如果发起端请求对端超时 会将请求的数据写入到缓存,其格式如下:
保存到 redis 中的类型:set
key: 捕鱼缩写(f) + "_" + 用户uid
value: "请求的命令 "+" @ " + [ k + "|" + value [ k + "|" + value ...] ]

实例 key = f_10001 value = req_mv_gold@gold=10000|session=1
含义为:捕鱼发起的请求(f) 用户uid(10001) 命令(req_mv_gold)和携带数据用 "@" 分割,数据中字段与字段用 "|" 进行分割。数据解析,按对应命令协议定义结构进行解析。

应用场景:

1.用户登录了捕鱼,进入捕鱼游戏,用户向斗地主发起请求 req_mv_gold 数据中 gold 字段值为 0,斗地主就把用户的金币先保存到临时变量,然后置空用户的金币,再把用户金币通过 rsp_mv_gold 发送给捕鱼,如果 rsp_mv_gold 没有收到响应,斗地主要把钱加回给用户,意味这一次转移金币失败

2.假如用户已经成功完成了上面的步骤,此时用户在斗地主中的金币值为 0,在捕鱼中的金币值为用户实际金币值。

3.等用户退出捕鱼游戏就再次向斗地主发起第一个步骤的请求,如果成功,则完成了金币转移,如果失败(可能斗地主服务器中,这个用户下线了,可能斗地主奔溃了,可能网络阻塞或者掉线),捕鱼会把这次的请求写入到 redis 中,也就是上面的这个例子。

4.用户再次登录斗地主时,斗地主服务器需要去redis中查看是否有 捕鱼缩写(f) + "" + 用户uid 的这个健的存在,如果存在了,就要读取该键全部的成员
如:SMEMBERS f_10001,(理论上来说,每种请求最多一条记录)并且删除掉 redis中的 捕鱼缩写(f)+"
"+uid 的健 如:DEL f_10001。并且按具体内容恢复数据。

这个机制适用于全部需要确保对端收到的命令。如果对端是捕鱼,那么 set 的键是 斗地主缩写(d) + "_" + uid,表示斗地主发起的请求失败了,捕鱼会按上面的流程自行处理。

你可能感兴趣的:(不同服务器之间的数据同步(skynet 和 c++))