在高并发情况下,如何实时构建TopN list

场景

  • 比如某个大型游戏举办大赛,要做一个实时的TopN列表,比如前一百名

解决方案

积分比较稳定并且最大涨/落幅度有限的情况

  • 如果说积分比较稳定,并且积分的增长和降落是有上限的(比如每天最多可以打m局游戏,并且每次最多涨/落maxp分),那么还是很好解决的
  • 首先在比赛开始前,我们对全量数据(假设数据库表中,积分这个字段是无序的)跑一次全量分析型事务,获得积分前n的所有人的列表,假设第n个人的积分是k,那么再获取到积分大于等于k-maxp*m的人的列表。那么我们可以预期比赛过程中的TopN一定在这些人中产生
  • 假设最后一个人是p分,那么对于比赛过程中出现的大于等于p分的人,也加入到list中,以保证这个list确实涵盖了前M名(M就是积分最少为k-maxp*m的人的数目)
  • 因为会出现“禁赛”等各种情况,所以可以以1.x倍去获取这个名单,更好的处理方案是按照下文的“积分比较稳定但是最大涨/落幅度无限的情况”去处理
  • 还有另一个措施,如果比赛过程中,我们这个list的人数低于一定值,那么就再跑一次全量分析型事务,去补充这个list
  • 全量分析任务如何跑?
    • 首先对于该全量数据某一时刻的快照,跑一次全量分析事务,拿到前百分之x的list
    • 假设拿到的list中,最后一名的分数p,再跑一次全量分析任务,把上一个分析任务过程中新加进来的大于p分的人加进list中
    • 注意,在跑这个新的分析任务时,新出现的,大于p分人的也要实时加入list中

积分比较稳定但是最大涨/落幅度无限的情况

  • 先获取前n*k(比如k是100)的人的list,可以期望TopN都出现在这个list中
  • 假设第n*k人是p分,那么对于比赛过程中出现的大于等于p分的人,也加入到list中,以保证这个list确实涵盖了前n*k名。当然,对于小于p分的我们也要清除掉
  • 然后如果比赛过程这个list中的人数低于一定值,跑一次全量分析任务,补充这个list

全量计算

  • 数据都放在红黑树中,然后每次用户改变自己的积分,就去更改该用户对应的node,然后对该树进行iter,拿到前n个用户,组成list