用Redis来搞定查询结果排序这事儿,真没那么复杂其实
- 问答
- 2026-01-05 03:01:01
- 19
这事儿还得从一个常见的场景说起,咱们做网站或者应用,经常有个需求,比如要展示“今日热榜”、“本周最受欢迎的作者”或者“这个商品被收藏最多”,后台数据库(比如MySQL)查起来倒是能查,但一旦访问的人多了,每次都去数据库里吭哧吭哧地分组、计算、排序,数据库的压力就很大,页面响应也会变慢,这时候,Redis就能帮上大忙了,它处理这种事儿特别拿手。
为啥Redis快?简单说,因为它把数据都放在内存里操作,速度自然比去硬盘里读写的数据库快得多,而且它提供了几种数据结构,天生就适合做计数和排序。
最常用的一个家伙叫有序集合,英文是Sorted Set,你可以把它理解成一个带了“分数”的集合,我们要做一个文章点赞榜, key 就叫 article:likes:ranking,每篇文章的ID就是集合里的“成员”,而这篇文章获得的总点赞数,就是它的“分数”。
当用户点一次赞,我们不用去更新数据库里的点赞数字段然后再重新计算排序,而是直接给Redis发一个简单的命令:ZINCRBY article:likes:ranking 1 文章ID,这个命令的意思是,在 article:likes:ranking 这个有序集合里,给“文章ID”这个成员的分数增加1,这个操作是瞬间完成的。
等到我们需要展示点赞Top10的文章时,只需要一个命令:ZREVRANGE article:likes:ranking 0 9 WITHSCORES,这个命令的意思是从大到小(ZREVRANGE里的REV就是reverse,反向的意思)取出排名从0到9的成员,也就是前十名,并且把它们的分数也一起显示出来,这个过程根本不需要复杂的计算,直接从内存里按分数排好序拿给你,速度快得惊人。
你看,整个过程,数据库只负责存储文章的基本信息(标题、内容等),而频繁变动的点赞数和实时排序这种“重活儿”都交给了Redis,数据库的压力一下子就小了很多。
除了这种简单的排行榜,有序集合还能玩出更多花样,来源文章《用Redis快速实现排序》里还提到了一个例子:实现一个“本周热议榜”,这涉及到时间范围,怎么做呢?我们可以每天凌晨创建一个新的有序集合,key的名字带上日期,article:likes:20240513,用户当天的点赞操作都记录在当天的集合里。
到了周末,我们需要统计这一周(七天)的数据总和,Redis提供了一个非常强大的命令叫 ZUNIONSTORE(求并集存储),我们可以用这个命令,把周一到周日的七个有序集合合并成一个新的集合 article:likes:weekly,并且在合并的时候,设置权重都是1,合并方式是SUM(求和),这样,新集合里每篇文章的分数,就是它这一周在所有七天里获得的总点赞数,我们再对这个新的总集合做一下 ZREVRANGE,本周的热议榜就瞬间生成了,这个操作虽然比单次的增加要耗时一点,但也是在内存里完成的,而且一天只做一次,完全能够接受。
再举一个例子,来源内容里还提到了用Redis的列表(List)结构来实现时间线排序,比如微博或者朋友圈的新鲜事,每发布一条新状态,就执行 LPUSH user:123:timeline "状态内容",把它塞到对应用户的时间线列表的头部,当用户查看自己的时间线时,用 LRANGE user:123:timeline 0 30 就能取出最新的31条状态,因为是从链表头部插入的,所以取出来的自然就是按发布时间倒序排列的,实现起来非常简单直接。
用Redis来做排序也不是说就万无一失了,因为它数据存在内存里,所以成本会比硬盘高,我们不能把所有数据都往Redis里塞,通常只放那些需要高频访问和排序的“热数据”,也要考虑Redis的持久化问题,以防服务器重启数据丢失,对于上面提到的这类排序需求,Redis的优势是数据库无法比拟的。
下次再遇到需要实时排序、排行榜之类的需求,先别急着去折腾数据库的SQL语句,想一想,能不能用Redis的有序集合或者列表来搞定,很多时候,真的就是几个简单的命令,问题就迎刃而解了,确实没那么复杂。

本文由符海莹于2026-01-05发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://www.haoid.cn/wenda/74700.html
