游戏开发工具

跨服服务器是游戏开发中常见的业务需求,由于一个游戏服务器的玩家承载能力是有上限的,通常我们会考虑采用多个游戏服的模式来进行分流,从而使更多的玩家可以流畅地玩游戏。

分服虽然可以降低单个游戏服务器的压力,但是却割裂了不同服务器玩家之间的联系,降低了游戏体验。

为了加强不同游戏服玩家之间的联系,避免不了增加一些跨服功能,最简单的比如跨服排行榜。

要实现游戏跨服排行榜,常规的做法是单独建立一个跨服服务器,通过跨服服务器,来进行集中处理和消息分发。大概就是下面这样一个结构,游戏服理论上可以很多,我只是简单画了两个示意一下。

1.jpg

每个服务器都要先把玩家的等级数据发往跨服服务器,然后在跨服服务器进行排序,排完了之后就,游戏服再从跨服服务器获取跨服排行。

功能实现倒是没什么问题,就是实际维护拓展的时候比较麻烦。

1、你要先写一个和跨服服务器传输数据的协议。

2、你要写一个跨服服务器处理排行榜并返回排行的协议。

3、每次更新新功能,你要同时更新游戏服和跨服服务器,一旦两边版本不一致,容易出现问题。

4、此外,如果这个玩家等级数据存在内存里,那么每次重启跨服服务器数据就会丢失,如果要做持久化存在数据库,那么又要单独写持久化的逻辑。

5、至于玩家的数据什么时候发送,是服务器启动发送还是玩家自己登陆发送,都会影响这个排行榜的准确性。

6、而如果要新增一种类型的跨服排行榜,以上所有都要再来一遍,极其繁琐。


基于以上种种,我一直在想能不能有更简单的跨服处理逻辑。比如,大家都往一个数据库写数据,再从同一个数据库读取数据,把数据库作为中心,围绕数据库进行数据排行。这样的好处不言而喻,数据的即时性和持久化可以一次性解决,但是随之而来的是新问题,如果每次都从数据库直接捞取排行榜,当用户大量点击排行榜的时候,数据库怕是扛不住这个压力,存在安全隐患。而如果在此之上架设一层缓存,就又会存在可能排行数据不同步的问题,因为你不知道其他服是不是写入了新数据。


所以Redis的出现,就完美解决了我的这个问题。Redis就是一个自带缓存又能像数据库一样持久化的工具。


Redis可以直接添加有序列表:

public Long zadd(String key, double score, String member) 
{
        this.checkIsInMultiOrPipeline();
        this.client.zadd(key, score, member);
        return this.client.getIntegerReply();
 }


Redis也可以根据需要倒序或正序读取列表。(以下函数为倒序列表,排行榜常用)

public Set<Tuple> zrevrangeWithScores(String key, long start, long end) 
{
        this.checkIsInMultiOrPipeline();
        this.client.zrevrangeWithScores(key, start, end);
        return this.getTupledSet();
 }

2.jpg

同时,借助redis管理工具,很容易查看和维护当前排行。同时,针对一些有时效性的跨服排行榜,比如天梯赛季排行榜,还可以做到给key添加过期时间,这样就不用担心数据膨胀的问题。

public Long expire(String key, int seconds) 
{
        this.checkIsInMultiOrPipeline();
        this.client.expire(key, seconds);
        return this.client.getIntegerReply();
 }


Redis的应用,让游戏排行榜的问题彻底解决。但是跨服服务器的功能不仅仅只有排行,有时候还需要处理一些逻辑,比如进行天梯匹配,进行赛季结算等等,如果不能解决这些复杂需求,跨服服务器就依旧有存在的必要。那么Redis有没有办法解决这些问题呢?我们下一期再讲。