Redis 的强大远不止于简单的缓存。它的美妙之处在于其丰富的数据结构和高性能的原子操作,能够以极其优雅和高效的方式解决许多常见的系统设计难题。
以下是一些超越基础缓存、体现 Redis “美妙” 之处的经典用法:
一、 数据结构的力量:不止是 String
Redis 的精华在于其多样的数据结构,每种结构都对应着一类特定的问题解决方案。
1. 排行榜与限流(Sorted Set - 有序集合)
美妙之处:一个数据结构,同时实现排序和范围查询,且性能极高。
- 典型场景:游戏积分排行榜、热门文章列表、延迟任务队列。
- 如何实现:
- 将成员(如用户ID)作为 member,分数(如积分、点击量、到期时间戳)作为 score 存入。
- ZADD leaderboard 1000 “user:123”
- 获取前十名:ZREVRANGE leaderboard 0 9 WITHSCORES (逆序取范围)
- 获取某用户的排名:ZREVRANK leaderboard “user:123” (逆序排名)
- 为什么美妙:传统数据库做实时排行榜需要 ORDER BY … LIMIT,数据量大时非常吃力。Redis 的 Sorted Set 底层是跳表,这些操作的时间复杂度都是 O(log(N)),性能极高。
2. 标签、好友和共同关注(Set - 集合)
美妙之处:高效的集合运算(交集、并集、差集)。
- 典型场景:
- 共同好友:用户A的好友存为一个 Set,用户B的好友存为另一个 Set,他们的共同好友就是这两个 Set 的交集 (SINTER)。
- 商品标签:一个商品有多个标签(如:商品:1000:tags -> {“优惠”, “数码”, “新品”})。可以通过 SINTER 找出同时拥有“优惠”和“数码”两个标签的所有商品。
- 为什么美妙:一次命令完成复杂计算,避免多次数据库查询和在应用层处理数据,速度极快。
3. 实时分析、计数和布隆过滤器(HyperLogLog 和 Bitmap)
美妙之处:用极小的空间完成海量数据的去重统计。
-
HyperLogLog:
- 场景: 统计网站的 UV (独立访客数)。可能有数千万的访问,你只关心数量,不关心具体是谁。
- 实现: PFADD uv:20251016 “user_ip_1” “user_ip_2”,然后 PFCOUNT uv:20251016 获取估算值。
- 为什么美妙:每个 HyperLogLog 键只需 12 KB 内存,就能计算接近 2^64 个不同元素的基数! 如果用 Set 存储,海量数据下内存会爆掉。
-
Bitmap (位图):
- 场景:用户签到记录。统计用户今年哪几天签到了。
- 实现: key 为 sign:202510:user:123,偏移量 offset 代表第几天。签到:SETBIT sign:202510:user:123 15 1 (第15天签到)。统计本月签到次数:BITCOUNT sign:202510:user:123。
- 为什么美妙:极其节省空间啊。365天的签到记录只需要 365 bit ≈ 46 字节。
二、 分布式系统的基石
4. 分布式锁 (String 与 Lua)
美妙之处:用简单的 SET 命令和 Lua 脚本,实现跨进程的互斥锁。
- 实现:
- 加锁:SET lock:resource_name my_random_value NX PX 30000
- NX:仅当 key 不存在时设置成功(抢锁)。
- PX 30000:设置 30 秒过期时间,防止锁持有者崩溃后锁永远不被释放。
- my_random_value:一个唯一值(如UUID),用于标识锁的持有者,防止误删别人的锁。
- 解锁(Lua脚本):
- 加锁:SET lock:resource_name my_random_value NX PX 30000
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
(为什么用Lua:GET 和 DEL 必须原子性执行,否则在判断后、删除前锁可能已过期并被别人获取,导致误删。)
- 为什么美妙:它是构建分布式系统的核心原语,用于控制分布式服务对共享资源的并发访问,实现简单且高效。
5. 消息队列 (List)
美妙之处:轻量级的、可靠的消息队列和生产者-消费者模型。
-
实现:
- 生产者:LPUSH task_queue <task_data> (将任务从左边推入列表)
- 消费者:BRPOP task_queue 30 (从右边阻塞地弹出任务,如果队列为空则等待30秒)
-
为什么美妙:虽然不如 Kafka、RabbitMQ 功能强大,但胜在极度轻量和简单。对于延迟要求不高、消息量不大的场景,用 Redis 做队列是性价比极高的选择。BRPOP 的阻塞特性避免了消费者无效的轮询。
三、 持久化与高可用
6. 延迟队列和定时任务 (Sorted Set)
美妙之处:利用分数代表执行时间,轻松实现“到时执行”。
- 实现:
- ZADD delayed_queue <future_timestamp> <task_data> (添加一个定时任务,分数是执行时间戳)
- 启动一个工作进程,循环执行:
-- 获取所有到期的任务
local tasks = redis.call('ZRANGEBYSCORE', 'delayed_queue', 0, <current_timestamp>)
-- 遍历 tasks,处理每一个到期任务
for _, task in ipairs(tasks) do
-- 处理任务
process_task(task)
-- 从队列中移除
redis.call('ZREM', 'delayed_queue', task)
end
- 为什么美妙:比 crontab 更灵活,可以动态地添加和取消定时任务,所有信息都集中存储在 Redis 中,易于管理。
Redis 的美妙,在于它用看似简单的组件(几种数据结构),通过巧妙的组合,高效地解决了分布式系统中的一系列核心问题。它提醒我们,好的设计不一定是复杂的,常常是简单和精准的。

被折叠的 条评论
为什么被折叠?



