p0po's blog

排行榜技术记录

排行榜一般都是异步任务跑出结果,将结果放入缓存,比如redis,然后将缓存中的结果展示给用户。
一般来说,大家都能想到这个方案,但是很多在展示的排行榜都忽略了一个要素,那就是排行榜生成时间,
对于异步生成的排行榜来说,这个至关重要,因为从严谨性考虑,应该给用户交代清楚,这个结果的有效时间范围。

排行榜需求是统计用户投资前100名。

开始为了完成功能:

在数据量少的时候,直接SQL统计结果出来,放到REDIS中,很简单,也很有效。

但随着数据量的增加,一个SQL肯定会越来越慢:

于是想到分页查询,在内存中统计结果,然后将结果放入到REDIS中,效果也还不错。

随着数据量的增加,每次统计IO越来越大,时间越来越长:

于是想到将查询到结果缓存到本地内存中,缓存中没有才去数据库查询,然后将其缓存到本地,即减少了和数据库的交互次数,又减少了每次统计时间,可以继续运转了。

随着数据量的增加,本地内存开始出现溢出告警,对于java程序来说,经常出现FULL GC:

于是将每个用户的投资总额放到redis,标记每次查询的时间,下次增量查询计算相关用户的投资总额,并改写用户在redis中的投资总额,
将每个用户的投资总额和排行榜中的最小值做比较,如果大于最小值,则放入排行榜,删除原来的最小值。

随着数据量的增加,没有出现什么大的问题,但上述方案存在隐患,后续验证后会补上。