Redis轻松优雅实现榜单功能

背景介绍

众所周知,在互联网项目中,我们用Redis的场景非常之多,Redis的出现,很大程度补偿了memcached这类key/value存储的不足,
在部分场合可以对关系数据库起到很好的补充作用,使用起来也是非常的方便,多种数据结构让你能更加优雅、轻松的面对各种场景,公司主要做直播行业的,
单纯Redis实例就有上百台,所以这边用Redis也是很频繁的,下面将介绍如果用Redis简易、轻松的去实现各种榜单。

场景模拟

1.日榜实现

假如有一个活动需求,需要你统计每天每个直播间收礼榜单以及贡献者榜单,思考下,你会怎么做?
嗯,聪明的你3秒钟不到就已经想到了要使用Redis的有序列表来进行统计,
没错,Redis的有序列表基本能实现大多的榜单统计功能,下面咱们先拿这个简单需求来开刀。

1.设计数据结构
字段名称定义(member):

{
    直播房间ID:roomId, 贡献者ID:userId
}

虽然贡献者可以在每个房间上榜,但房间ID唯一,所以根据这两ID组合可保证唯一性

根据当地时间作为KEY(key)例如 20210630 确保每一天榜单


送礼总价值(score):这个玩意是异步处理的,所以确保每次计算就行了

2.操作
ZADD key score member
至此完事

3.查询
ZREVRANGE key start stop

这样子就将每天的榜单查询出来了,so easy!

2.周榜实现

单纯按自然周来统计的话,跟日榜没啥区别,如果时最近N日榜单,假设继续上面的活动需求,不仅要每日榜单,还需要看近N日的榜单,这时你会怎么弄?

你要是存在数据库里,这个问题非常的好办,直接SQL按时间周期查就完事了,
当然这种高频热点数据你反复在库里读写简直就是找死。

由于Redis这玩意是非关系型,好家伙这时你可能会把每一天数据查出来然后再统一排序?
这种方式当然不可取,首先每天的数据榜单都是一个独立KEY,每个KEY的member和score都是不同的,这种方式虽然可实现,但整体接口响应时间...
前期数据少可能没啥影响,一但量大了,这就是挖坑,后面还得自己填。

正确做法是使用redis有序列表自带的合并操作

命令:
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] [AGGREGATE SUM|MIN|MAX]
别看命令这么长啊,其实很简单:
destination:目标KEY 这里命名一个新KEY,用于查询近N日榜单的KEY
key:你可以填当日
numkeys:要合并KEY的数量   查询近N-1天,这里填N-1
[key ...]:要合并KEY名称数组 N天前除了当日的KEY名称
WEIGHTS: 乘法因子
AGGREGATE:聚合的方式,我们这边计算的是总榜所以使用SUM
当然,你用redis封装的库的API使用起来更加简单、优雅

合并操作时间复杂度:O(N)+O(M log(M)), N 为给定有序集基数的总和, M 为结果集的基数。

总结

采用Redis实现榜单具有天然的优势,其丰富的数据结构,简易使用的API让我们能轻松实现一个榜单功能,当然用的时候也要注意以下几个问题

  1. 使用时缓存击穿与缓存穿透的问题
  2. Redis宕机(主从、集群架构下基本很少出现)、 Redis服务不可用时的预案处理
  3. 缓存一致性问题

路漫漫其修远兮,吾愿与君上下而求索,非常感谢各位帅哥、靓妹的点赞、收藏和评论,关注我,只实战不理论,我们下期见

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Redis 是一个开源的高性能键值存储数据库,常用于缓存、队列等场景。在实现榜单功能时,可以利用 Redis 的有序集合(sorted set)数据类型来实现。 有序集合(sorted set)是一种有序的数据结构,其中的每个元素都会关联一个分数(score),根据分数进行排序。利用这个特性可以实现榜单的功能,将每个用户或物品作为有序集合的一个成员,分数即为该用户或物品的排名。 首先,我们需要将用户或物品的分数和排名信息存储到 Redis 中。可以通过命令`ZADD`向有序集合中添加成员及其分数,例如: ``` ZADD leaderboard 1000 "user1" ZADD leaderboard 800 "user2" ZADD leaderboard 500 "user3" ``` 上述命令表示向名为`leaderboard`的有序集合中添加了三个成员,分别为`user1`、`user2`和`user3`,对应的分数分别为 1000、800 和 500。 接下来,我们可以利用`ZREVRANGE`命令按照分数的高低返回排行的前几名,例如: ``` ZREVRANGE leaderboard 0 2 WITHSCORES ``` 上述命令表示返回`leaderboard`有序集合中分数最高的 3 个成员及其分数。通过这个命令可以获取榜单的排名和分数信息。 另外,还可以通过`ZINCRBY`命令对某个成员的分数进行增减操作,例如: ``` ZINCRBY leaderboard 100 "user1" ``` 上述命令表示将`user1`成员的分数增加 100,可用于更新用户或物品的排名。 通过以上的 Redis 命令,我们就可以实现榜单的功能。在实际应用中,可以结合定时任务或触发器,周期性地更新榜单中的成员分数,从而保证榜单的准确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

消灭知识盲区

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值