在游戏的设计中,我们需要设计一个贸易利润和综合实力排行榜。在排行榜中,我们有这样的需求:
A: 排行榜4天更新一次,也就是,需要统计玩家4天内贸易利润和综合实力
B: 上榜的玩家有奖励发送。
C: 综合实力是统计全服玩家,如果玩家分库存储,需要遍历所有的玩家库
D:4天后,删除旧数据,更新原来的数据。
E:排行榜是全服共享的
F:上榜的玩家的信息是动态的,如,玩家的等级,玩家的国籍(游戏中,可以允许玩家修改国籍)
G: 我的排名显示,和排行榜中的排名显示,要一致。
我们在做最后一个需求的时候,出现过这样的问题,排名榜是全服共享的,而我的排名是我从数据库中实时读出来的,也就是说,当玩家A第一次查看排行榜的时候,此时会缓存排行榜的数据1个小时,如果玩家B在过来看排行榜的时候,其实,这个排行榜是玩家A缓存的。但是,“我的排名”是从数据库实时读出来的,如果玩家B在榜上,而且已经被缓存了,那么如果玩家B的排名发生变化,且缓存还没有失效,那么玩家的的排名就会和排行榜上的有所不同。
解决做法:
A 缓存我的排行榜和我的排名的数据。
B 读取我的排名的时候,如果他在排行榜上,优先读取排行榜中的排名
C 当更新排行榜的缓存的时候(即清空原来的缓存,然后缓存最新的信息),同时,清空 “我的排名” 的缓存。防止排行榜中的排名和我的实际排名不一致的问题
还有一个最大的问题:
排行榜的数据缓存1小时。每过4天后,重新统计排行榜的信息。也就是说,4天后,排行榜中的信息全部失效,重新统计,如果此时,被缓存的排行榜数据没有失效,那么,我读出来的排行榜的数据还是原来的数据。
怎么解决这个问题:
最初的想法是,直接删除原来缓存的数据,可是怎么删除呢,这个做法不可行。
最好的做法是,在缓存的key里面加入时间,如果时间过期,就不会读这个key对应的内容。
$cacheKey = 'Rank:' . $field . ':' . $year;
设计思路:
创建一个rank表,统计玩家4天内的贸易利润。
创建一个奖励配置rank_award表,给上榜的玩家发放奖励。