爱陪小樱桃

导航

 

排行榜的思考:

遇到排行榜,大家就想到数据库的orderby
比如:微信运动
这个实现是没有问题的,如果表的数据量少的话,推荐使用

大量数据的排行榜:如果在亿级别的数据,同时很多并发的情况下,怎么办?

使用上述的方法:磁盘扛不住,排序算不动,并发撑不起来:

当数据量较大:并且实时更新&&频繁查询的时候,使用Redis的zset有序集合更合适。
redis 排序快,扩展性强,能轻松应对高并发。
redis的数据是全放内存,避免磁盘读写,核心操作秒回。

-- redis通过分片存储,拆分到多个实例,比如1亿用户分配到10个小库,每个小库处理1000万数据
1.线性扩展:加快提升容量和性能
2.压力分散:读写请求分配到不同分片,避免单点瓶颈
3.独立扩容:热点分片可以独立的升级配置,不干扰其他节点

-- 高并发也轻松
1.闪存闪读:比磁盘块10万倍。
2.单线线程无锁:比多线程切换锁,原子操作不怕并发冲突。
3.IO多路复用:一个线程监听万个连接,像一个人同时处理多个业务窗口

单机Redis可以扛10万+QPS,分片集群轻松破百万并发。

遇到问题

如果所有的用户:都来查询top100,那么久容易造成热点key的问题,这样会导致:所有的请求都请求到一个key上,容易导致单分片cpu和宽带被打满,极端情况Redis实例崩溃,排行瘫痪。

方法1:多级缓存解决上边的问题:
1.请求优先读取本地内存缓存,
2.缓存未命中的时候读Redis集群
3.Redis集群内部缓存Top100(设置更新的TTL)

方法2:读写分离+从库负载均衡
主库处理写的操作,更新排行分数,从库轮询处理读的操作。

分片key设计
将排行榜按照分数区间拆分成多个key,例如:
key1:top1(前100)
key2:top2(101-1000)

这样查询前100只需要查询top1

问题2

内存爆炸:
存储:若每个键存储32字节,仅仅是建就存储了3.2G,加上分数和指针内存压力巨大。
1.缩短键的名字,2.分片存储:按照ID哈希分片存储。

宕机数据丢失,持久化存在风险

redis宕机会导致,数据更新丢失。即使重启也会丢失。
解决方案:
异步双写:更新分数的时候:同步写入消息,有消费者异步落库,用于故障恢复。
混合持久化:开启RDB+AOF,平衡恢复速度与数据完整性。

实现方案:分治:

1.按照区间拆分
--把排行榜切小块蛋糕,比如:
高分玩家:【放入金盘子】rank2500-2600、
中分玩家:【放入银盘子】rank2400-2500、
中分玩家:【放入其他】rank0-2400、
这样一来top100只需要翻转第一个盘子,不需要全部搅动。

2.动态路由
玩家积分变化的时候,自动按照代码等级移动到对应的盘子里面去。
3.聚合查询
然后从高到低翻找盘子,先找金盘子,不够在去找银色盘子。
比如先找金盘子50,不够银色盘子捞50,然后在把这100个人排序。

posted on 2025-08-14 21:32  cherry小樱桃  阅读(12)  评论(0)    收藏  举报