游戏中的离线玩家
一般的游戏架构都有 数据库 + 缓存 这样的存储机制,而这个机制决定了离线玩家的实现方式。其中一种很常用的做法是将所有玩家的信息全部都加载到内存中,当要查找离线玩家信息时,直接可以在内存中获得,不需要再到数据库中查找。其实我一直觉得这其中有一些问题,那就是随着时间的推移,内存的有效利用率越来越低。原因很简单,(从趋势上来讲)整个游戏的玩家活跃度会随时间慢慢降低。特别是合服之后,这种负面效果将会加倍。很可能为了1%的玩家,浪费了99%的内存。而且加载全部玩家信息还可能会遇到其他问题,例如超出数据包容量限制等。当然,这些问题取决于你本身使用的框架设计。
说回我的离线玩家设想。
在数据库中设计两个表:
1、全部玩家信息表(表A),就算不做离线玩家信息查找,这个表也是存在的。
2、最近玩家信息表(表B),表结构跟表A一样,只是表B只保存最近登录的玩家信息。
在内存中维持两个列表:
1、最近登录玩家列表(列A),保存最近登录过的玩家信息列表,玩家登录,会将其信息放到列表头。
2、最近被查找离线玩家列表(列B),不跟数据关联,只存在内存。
首先,服务器启动时会到数据库加载表B到列A,玩家登录,会更新列A。当查找离线玩家信息时,到列A找,找不到,再到列B找,再找不到,到数据库找。当从数据库中找到数据,一并将其保存到列B,那么列B相当于临时保存了最近部分活跃但没有登录过的离线玩家信息,其中的活跃是被动活跃,即被别的玩家查找过。数据保存时,列A只保存列表前N个玩家的信息(N是一个经验值),列B不保存数据库,只在内存中维护。虽然只保存列A前N个玩家的信息,但是只要服务端不重启,N个之后的玩家依然在列A中。当然在加载与保存之间,也是要对列表的状态进行维护,例如玩家属性更新了,要与列A同步。玩家登录时,自动插入数据到列A,如果你还要保证数据唯一性,那么当玩家上线时,如果玩家存在于列B,也要将其从列B删除(其实不删除也是可以的)等等。
优点:
列A相当于一级缓存,列B相当于二级缓存。结合我的游戏经验,列A的命中率应该是非常高的了。因为一般都是活跃玩家才会查看其信息。
在游戏开服对服务端运行效率要求高时,这时列A保存了所有玩家的信息(新开服每个玩家都有登录过),不需要到数据库查找,也不需要到列B查找。
【游戏中的离线玩家】在游戏运行一段时间后,对服务端运行效率的要求下降(在线玩家减少),因此偶尔访问一下数据库,不伤害游戏体检,而且可以大大节省机器内存。
PS:
虽然我一直说列A、列B,但是它们不是列表结构(List),而是一种混合的数据结构,姑且称为快速列表(FastList)。它可以是Map + List的结构,也可以是Hash + List的结构。Map(Hash)是为了快速查找,List是为了插入与删除。
推荐阅读
- 热闹中的孤独
- JS中的各种宽高度定义及其应用
- 游戏IP(立足于玩家情感的粉丝经济)
- 我眼中的佛系经纪人
- 《魔法科高中的劣等生》第26卷(Invasion篇)发售
- Android中的AES加密-下
- 放下心中的偶像包袱吧
- C语言字符函数中的isalnum()和iscntrl()你都知道吗
- C语言浮点函数中的modf和fmod详解
- C语言中的时间函数clock()和time()你都了解吗