Redis那些你没注意的用法,教你玩转不止一点点技巧
- 问答
- 2026-01-03 20:27:56
- 10
说到Redis,很多人第一反应就是个缓存数据库,set(设置)、get(获取)、del(删除)三板斧,但其实Redis就像一个多功能瑞士军刀,你只用了它开瓶器的功能,却忽略了它还有小刀、锯子、剪刀等等一大堆好用的家伙事儿,今天咱们就聊聊那些你可能没太注意,但知道了之后会直呼“原来还能这么玩”的Redis用法。
用ZSET(有序集合)实现一个轻量级的时间轴或者排行榜
你以为ZSET只能做游戏排行榜?那可就大材小用了,它的本质是给每个成员(member)绑定一个分数(score),然后可以按照分数排序,这个“分数”不一定非得是游戏得分,它可以是时间戳。

- 用法示例:比如你要做一个微博那样的动态时间轴,每当用户发布一条新微博,你就可以执行
ZADD user_timeline:用户ID 时间戳 微博内容ID,这里,时间戳就是分数,那么获取这个用户最新的20条动态,只需要ZREVRANGE user_timeline:用户ID 0 19,完美实现按时间倒序排列,如果你想看某个时间点附近的动态,还可以用ZRANGEBYSCORE命令进行范围查询,非常灵活。 - 进阶玩法:你甚至可以用它来做延迟队列,把需要处理的任务作为member,把希望执行的时间点作为score塞进ZSET,然后起个定时任务,用
ZRANGEBYSCORE key -inf 当前时间戳把到点的任务捞出来处理。
用BITMAP(位图)做用户签到统计,省到极致
如果你要记录用户一年的签到情况,用传统的String类型,每个用户每天一条记录,数据量会非常吓人,但用BITMAP,一个用户一年的签到记录只需要 365个比特位,也就是大概46个字节就能搞定,节省了惊人的空间。
- 用法示例:假设用户ID是1000,今天是2024年的第100天,签到就是
SETBIT sign:2024:1000 100 1,检查某天是否签到用GETBIT sign:2024:1000 100,统计这个月签到天数用BITCOUNT sign:2024:1000 起始偏移量 结束偏移量。 - 进阶玩法:BITMAP还支持位运算,比如你想知道2024年5月1号这天,哪些用户既在App上活跃又完成了付费(假设你有两个不同的位图记录这两种行为),你可以用
BITOP AND result_bitmap active:20240501 paid:20240501,然后读取result_bitmap中为1的位对应的用户ID就行了,非常适合做大规模用户行为分析。
用HyperLogLog(HLL)进行海量数据去重计数,牺牲精准换空间

如果你的老板让你统计一下网站首页一天的独立访客数(UV),你可能想到用SET把每个访问者的IP存起来,然后用 SCARD 命令计算集合大小,这在小流量时没问题,但如果IP量达到百万、千万级别,这个SET会占用非常大的内存,HyperLogLog就是来解决这个问题的。
- 用法示例:每个用户访问时,执行
PFADD page:index:uv 用户IP,注意,HLL只会添加不重复的元素,统计UV就是PFCOUNT page:index:uv,它的神奇之处在于,无论你添加了多少个元素,一个HLL结构只需要占用大约12KB的内存,并且计算出的基数(不重复元素个数)的误差率可以控制在0.81%以内。 - 注意事项:HLL不是百分百精确,它适用于那种“大概看看有多少人”的场景,比如UV统计、搜索关键词的不同个数统计等,你不能从HLL中取出具体添加了哪些元素,它只是个计数器。
用GEO(地理空间)功能轻松实现“附近的人”
你可能觉得实现“附近的人”需要依赖专门的地理信息系统(GIS),非常复杂,但Redis在3.2版本之后内置了GEO功能,底层是用ZSET实现的,让这个功能变得异常简单。

- 用法示例:当用户上传位置时,执行
GEOADD drivers 经度 纬度 司机ID,就把司机的位置信息存进去了,现在有乘客想找附近3公里内的司机,只需要执行GEORADIUS drivers 乘客经度 乘客纬度 3 km WITHDIST,Redis瞬间就能返回符合条件的司机ID列表,并且还能附带他们距离乘客有多远(WITHDIST选项)。 - 核心原理:它通过一种叫Geohash的算法将二维的经纬度坐标编码成一维的分数,存放到ZSET中,所以附近的点其Geohash值也是相近的,查询起来效率极高。
用LIST的阻塞操作实现简单的消息队列
虽然现在有Kafka、RabbitMQ等专业的消息队列,但在一些简单的、轻量级的场景下,用Redis的LIST做消息队列就足够了,而且非常简单。
- 用法示例:生产者用
LPUSH task_queue 任务内容将任务放入队列,消费者用BRPOP task_queue 30来获取任务,这个命令的“B”代表阻塞(Block),如果队列为空,消费者会等待最多30秒,期间有任务进来就立刻弹出,避免了消费者不停轮询浪费资源,这就像一个简单的FIFO(先进先出)队列。 - 局限性:这种队列没有ACK确认机制(消息被消费后需要确认,否则可能被重复消费),如果消费者拿到任务后崩溃了,这个任务就永久丢失了,所以它适合处理一些允许丢失的非关键任务。
用PUB/SUB(发布订阅)做实时消息推送
这个功能让Redis成了一个简单的消息广播站。
- 用法示例:比如一个在线聊天室,每个用户连接上服务器后,服务器就让这个用户订阅(SUBSCRIBE)一个叫
chat_room:1的频道,当有用户发言时,服务器就向这个频道发布(PUBLISH)一条消息PUBLISH chat_room:1 "用户A:大家好!",所有订阅了chat_room:1频道的用户都会实时收到这条消息。 - 注意事项:PUB/SUB是“fire and forget”(发射后不管)的模式,消息没有持久化,如果一个订阅者当时不在线,它就收不到这条消息,所以它适合在线实时推送,不能用于保证消息必达的场景。
Redis远不止是个缓存,它的数据结构丰富多彩,巧妙运用这些数据结构,可以用非常简洁的代码和极低的资源消耗,解决很多看似复杂的业务问题,下次当你设计功能时,不妨先想想:“这个问题,用Redis的那把‘小刀’能不能优雅地解决呢?”
本文由凤伟才于2026-01-03发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://waw.haoid.cn/wenda/73907.html
