假设微博热度排行榜是根据点赞数量排名
怎么实现?
可以用Redis的有序集合实现,外层key是固定前缀+排行榜名称,内层value是微博ID,对应的score是点赞数量。每次点赞可以用
zincrby key increment score
命令给每条微博增加对应的点赞数量。
大key问题
微博数量很多,如果都放在一个key,那就会产生大key问题。可以把一个key拆分成多个key,比如100个key,每个key只存储一部分微博。然后用一个汇总的key保存排名前N的数据
1)这100个key还是保存在一个Redis中。以lua脚本的方式执行下面的命令
// 写操作
zincrby key_{1-100} increment score;
zincrby key_sort_{N} increment score;
// 如果已经包含N个元素,删除最小的一个
if(zcard key_sort_{N}>N){
zremrangebyrank key_sort_{N} 0 0;
}
// 读操作
zrevrange key_sort_{N} 0 -1 WITHSCORES
2)假设这100个key是分布在不同的redis上面。那么就不能使用lua脚本了
同样的思想,拿出一个汇总的key来保存排行前N的数据。
每次写操作后,异步地将这条微博的点赞数量增加到这个汇总的key上面,命令如下:
// lua脚本执行下面2条命令
zincrby key_sort_{N} increment score;
// 如果已经包含N个元素,删除最小的一个
if(zcard key_sort_{N}>N){
zremrangebyrank key_sort_{N} 0 0;
}
允许有时候异步线程更新汇总key失败,总不会每次都失败。查询排行前N同上。
拓展
1)不单根据点赞数量排名,还有浏览数量,怎么设计?
2)redis的数据是保存在内存的,如果还没持久化或者说某一段时间里key的排名发生了变化,但还没持久化,redis重启后,会造成用户在前面看到的排行榜和后面看到的排行榜发生了变化,怎么解决?