最近看redis相关的书籍,发现zrevrangebyscore在目前的业务中使用场景非常多,所以下面通过特殊的案例来分享一下zrevrangebyscore的使用。微博推荐,时事新闻,聊天记录拉取等应用中,数据都会按照时间排列,形成有序队列。下面我们会根据这类应用来讲解一下实际的案例使用。
Redis zrevrangebyscore 返回有序集中指定分数区间内的所有的成员。有序集成员按分数值递减(从大到小)的次序排列。具有相同分数值的成员按字典序的逆序(reverse lexicographical order )排列。
完整的使用示例
代码语言:javascript复制zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count]
参数说明
指令 | 是否必须 | 说明 |
---|---|---|
ZREVRANGEBYSCORE | 是 | 指令 |
key | 是 | 有序集合键名称 |
max | 是 | 最大分数值,可使用” inf”代替 |
min | 是 | 最小分数值,可使用”-inf”代替 |
WITHSCORES | 否 | 将成员分数一并返回 |
LIMIT | 否 | 返回结果是否分页,指令中包含LIMIT后offset、count必须输入 |
offset | 否 | 返回结果起始位置 |
count | 否 | 返回结果数量 |
案例1:
微博的推荐,这个推荐一般都会基于一个用户来保存一个有序队列,然后用户拉取最新的推荐微博则基于当前的position进行拉取最新的数据,微博的数据我们设置成score的值是唯一并且自增的。
首先我们根据一个用户添加已有3条数据
代码语言:javascript复制zadd weibo_recomend_1 2021081101 '{"title" : "recomend1","content":"xxx1", "time": 2021081101}'
zadd weibo_recomend_1 2021081102 '{"title" : "recomend2","content":"xxx2", "time": 2021081102}'
zadd weibo_recomend_1 2021081103 '{"title" : "recomend3","content":"xxx3", "time": 2021081103}'
假如用户打开微博访问了第一页,则会拉取第一页的数据。执行命令如下:
代码语言:javascript复制zrevrangebyscore weibo_recomend_1 inf -inf LIMIT 0 2
返回数据如下
代码语言:javascript复制1) "{"title" : "recomend3","content":"xxx3", "time": 2021081103}"
2) "{"title" : "recomend2","content":"xxx2", "time": 2021081102}"
当用户向下滑动,前端需要把第一次的最小一个position值(2021081102)传上来,redis执行命令如下:
代码语言:javascript复制zrevrangebyscore weibo_recomend_1 2021081101 -inf LIMIT 0 2
返回结果如下
代码语言:javascript复制1) "{"title" : "recomend1","content":"xxx1", "time": 2021081101}"
如果这个时候有插入新数据,插入新数据如下:
代码语言:javascript复制zadd weibo_recomend_1 2021081104 '{"title" : "recomend4","content":"xxx4", "time": 2021081104}'
微博会提示有一条新微博消息,用户网上拉,前端会把当前最大的position值(2021081103)传上来,则执行命令如下
代码语言:javascript复制zrevrangebyscore weibo_recomend_1 inf 2021081104 LIMIT 0 2
返回结果
代码语言:javascript复制1) "{"title" : "recomend4","content":"xxx4", "time": 2021081104}"
案例2:
新闻推荐,我们如果使用redis做缓存拉取分页数据,有序集合是非常方便使用的,下面我们看下新闻的上拉和下拉的实现。
添加5条新闻
代码语言:javascript复制zadd news 202110022301 '{"title" : "new1", "time": 202110022301}'
zadd news 202110022302 '{"title" : "new2", "time": 202110022302}'
zadd news 202110022303 '{"title" : "new3", "time": 202110022303}'
zadd news 202110022304 '{"title" : "new4", "time": 202110022304}'
zadd news 202110022304 '{"title" : "new4_1", "time": 202110022304}'
zadd news 202110022305 '{"title" : "new5", "time": 202110022305}'
当用户第一次打开新闻页面会执行如下操作
代码语言:javascript复制ZREVRANGEBYSCORE news inf -inf LIMIT 0 3
返回结果
代码语言:javascript复制1) "{"title" : "new5", "time": 202110022305}"
2) "{"title" : "new4_1", "time": 202110022304}"
3) "{"title" : "new4", "time": 202110022304}"
基于第一页下拉,则需要把最小的position(202110022304)和这个position展示多少条数据的值提交给后端position_count(),则后端执行的命令如下:
代码语言:javascript复制zrevrangebyscore news 202110022304 -inf LIMIT 2 3
返回结果
代码语言:javascript复制1) "{"title" : "new3", "time": 202110022303}"
2) "{"title" : "new2", "time": 202110022302}"
3) "{"title" : "new1", "time": 202110022301}"
新增一条新的新闻
代码语言:javascript复制zadd news 202110022306 '{"title" : "new6", "time": 202110022306}'
基于第一页上拉最新的数据score的数据有重复的,则需要前端传上次最后一个position和这个position对应的数据值,然后请求上报过来,则可以在程序中过滤掉展示过的数据。分页的条数不一样问题不是很大。当然如果我们保证新闻中的score是自增的并且是唯一的,则可以参照案例1的方式进行读取上拉,下拉的数据。
总结:
1:redis的zrevrangebyscore是最常用于分页使用的。
2:如果要使用zrevrangebyscore分页我们需要注意写入的score尽量保证是有序并且唯一的,这样我们才能方便的使用分页处理业务逻辑