Redis
2025/5/21大约 3 分钟
Redis 缓存穿透、缓存雪崩和缓存击穿分别是什么,如何解决?
| 问题 | 现象 | 解决方案 |
|---|---|---|
| 缓存穿透 | 查询不存在的数据,请求直达数据库 | 布隆过滤器、空值缓存 |
| 缓存雪崩 | 大量缓存同时过期,请求直达数据库 | 随机过期时间、互斥锁 |
| 缓存击穿 | 热点key过期瞬间,大量请求直达数据库 | 互斥锁、永不过期、二级缓存 |
Redis 有哪些数据类型?
| 类型 | 特点 | 典型场景 |
|---|---|---|
| String | 二进制安全,最大512MB | 缓存、计数器 |
| Hash | 键值对集合,适合存储对象 | 用户信息、商品属性 |
| List | 字符串链表,支持两端操作 | 消息队列、最新列表 |
| Set | 无序不重复集合 | 标签、共同好友 |
| ZSet | 有序集合,按分数排序 | 排行榜、延迟队列 |
| HyperLogLog | 基数统计,内存占用小 | UV统计 |
| Bitmap | 位图,支持位运算 | 用户签到、在线状态 |
用 Redis 怎么实现队列?
1. 使用 List 实现简单队列
Redis 的 List 数据结构天然支持队列操作,一端添加元素,另一端取出元素。
# 生产者推送消息到队列尾部
RPUSH queue:message "任务内容"
# 消费者从队列头部取出消息
LPOP queue:message
# 阻塞式取出(无消息时等待,避免频繁轮询)
BLPOP queue:message 30 # 最多等待30秒特点:简单易用,适合基础队列需求,但消息消费后即删除,不支持重复消费。
2. 使用 List 实现优先级队列
通过多个 List 模拟不同优先级的队列,消费者按优先级顺序处理。
# 高优先级任务入队
RPUSH queue:high "紧急任务"
# 普通优先级任务入队
RPUSH queue:normal "普通任务"
# 消费者先检查高优先级队列
LPOP queue:high # 优先处理高优先级
LPOP queue:normal # 高优先级为空时处理普通任务特点:实现简单,但需要消费者主动轮询多个队列,优先级数量固定时适用。
3. 使用 ZSet 实现延迟队列
利用 ZSet 的有序特性,将执行时间作为分数,实现定时任务队列。
# 添加延迟任务(时间戳作为分数)
ZADD delay:queue 1625097600000 "任务ID1" # 指定时间戳执行
ZADD delay:queue 1625097700000 "任务ID2"
# 获取当前时间到期的任务
ZRANGEBYSCORE delay:queue 0 $(date +%s)000
# 处理完成后删除任务
ZREM delay:queue "任务ID1"特点:支持精确的延迟执行,适合定时任务场景,但需要额外的时间管理逻辑。
4. 使用 Stream 实现消息队列(Redis 5.0+)
Stream 是 Redis 5.0 引入的专门用于消息队列的数据结构,功能更完善。
# 生产者发送消息
XADD stream:messages * name 张三 age 25
# 创建消费者组
XGROUP CREATE stream:messages mygroup 0 MKSTREAM
# 消费者读取消息(未确认消息会保留)
XREADGROUP GROUP mygroup consumer1 COUNT 1 STREAMS stream:messages >
# 消息处理完成后确认
XACK stream:messages mygroup 1625097600000-0特点:
- 支持消费者组,实现消息广播
- 消息确认机制,确保不丢失
- 支持消息回溯,可读取历史消息
- 适合复杂的消息队列场景
各方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| List | 简单高效 | 消息即删,不支持重复消费 | 简单队列、任务分发 |
| 多List | 实现简单 | 需轮询,优先级固定 | 优先级任务处理 |
| ZSet | 支持延迟执行 | 需要额外时间管理 | 定时任务、延迟队列 |
| Stream | 功能完善 | Redis 5.0+,相对复杂 | 可靠消息队列、事件流 |