对游戏PVP系统的数据缓存思考

最近我们策划丢过来一个需求,需要进行PVP的异步对战,由于是异步对战所以原来对玩家数据的缓存方式就不再可行,需要进行一些改动。

由于在异步对战中需要查找不在线的玩家的数据,那么我们需要尽可能多的玩家的部分数据缓存在内存中,并提供一定的机制方便查询。

1.原有的存储机制:
原有的存储机制有两个存储执行点。
(1)对修改的数据做标记,将修改的非金钱数据加上玩家和系统的标签值传入消息队列中(类似user_12_package,表示玩家id为12的背包数据存储)由一个专门的goroutine来进行存储;对于金钱数据直接调用数据库接口立即存储;
(2)对于离线超过5分钟的玩家数据,传入另外一个数据存储goroutine立即存储.

2.原有方案的问题
原有的方案由于缓存时间过短、缓存数据过多,这对尽可能长时间和尽可能多的缓存玩家部分数据的目的无法完成。

3.改进方案
首先我们需要搞清楚我们需要的数据,然后确定缓存数据的时间和同步机制。

(1)PVP需要的数据
由于PVP的异步战斗主要需要的核心数据是玩家对应角色的英雄信息、技能信息、装备信息,那么我们在缓存中仅需要缓存玩家的这三类信息即可。

(2)缓存时间
这个时间目前我们还没有最终确定,暂定的是24小时缓存。同时我们会保留24小时内活跃的PVP玩家分值段附近的玩家数据,以便提高命中率。

(3)缓存数据同步
写同步:缓存中的三类信息是与数据库中的数据保存一致,在完成数据库写入之后会同步给该缓存系统。
读同步:玩家登陆时候加载数据优先读取缓存数据,如果缓存数据不存在再从数据库中拉取并同步到缓存系统。
超时:超时直接释放。

(4)处理缓存中不存在数据
在缓存系统中,保留了最近一个月所有登陆玩家的分段信息和玩家基础信息(名字、ID);如果在缓存中未找到对应分段的玩家三类信息,那么我们会通过查找该表,开启一个新的goroutine将该分段附近的玩家信息立即加载到缓存系统中。
这里我们使用了锁机制,避免同时有对应的玩家登陆,重复加载数据造成复杂的问题。

通过改进之后,玩家离线超过5分钟后释放的信息将变少,内存中保留的信息将变多,会导致内存占用加大,这个需要具体的测试调整具体缓存玩家的信息数量,如果占用内存超过物理限制,进程是会崩掉的,recover是没有任何用的。

注:服务器开发采用的是go语言,文中出现的函数名和关键字均为go语言包含的信息。