高性能排行榜通用设计

1.整体设计

  1. 用户id取模,放到到redis槽位的排行榜(lotter:user:01 ~ lotter:user:127),存放top1000
  2. 定时任务定时将分片槽位排行榜汇总到lottery:top,取Top1000
  3. 本地缓存lottery:top,定期刷新

2.流程图

image.png

3.流程

  1. 分128(支持可配置)个key的zset(lottery:user:01),根据0~127。每个只存1000(可配置)条数据
  2. 每次积分更新,用uid对128取模找对应的槽位,落到对应的zset
  3. 起一个定时任务,定时将这个128key的放入另外一个最终排行榜zset,也是只取前1000(可配置)条数据
  4. 服务再使用本地缓存,缓存这个zset,根据需求,10s更新一次或者1min更新一次

4.落库

这里的流程图是没考虑落库的,但是实际中,是需要考虑的。根据业务形态来,可以考虑设计积分表,分库分表,然后异步落库。
当然如果压力不大,可以考虑去先写库再写redis,但是针对一些超高并发、并且是短期的排行榜,可以考虑就存redis,然后异步写mysql,同时记得打日志,到时候方便回溯。

5.考虑点

  1. 拆分成128个对应槽的Zset:
    是由于考虑存在读写热点、以及大key问题。所以改成128个,将写压力分摊到多个redis节点。
    同时我们这里用的槽位,这样redis的扩、缩容不影响数据
  2. 定时任务更新到排行榜Zset:
    这里不考虑实时,如果更新频繁,可以将定时任务的间隔调小(秒级别、分钟级别、小时级别、天级别),不然前面的拆分就失去了意义,仍然存在热点key
  3. 本地缓存排行榜:使用本地缓存来解决排行榜读的压力,否则排行榜Zset又会重新新的热点Key
  4. 考虑批量写、批量读
  5. 活动中期对于排名靠后的用户,根据业务规则,可以考虑不参与排序,减少压力
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容