一、Redis 如何实现消息队列?
1 为什么需要消息队列?
先想一个常见场景:
用户下单:
用户 → 下单服务 → 库存服务 → 物流服务 → 通知服务
如果全部 同步执行:
用户请求会非常慢
于是我们把流程改成:
用户
↓
下单服务
↓
写入消息队列
↓
库存服务消费
物流服务消费
通知服务消费
这样:
下单接口立即返回
消息队列负责:
异步处理任务
2 Redis 如何实现队列?
Redis 最早使用的是:
List
Redis List 本质是一个 双端链表。
支持操作:
LPUSH
RPUSH
LPOP
RPOP
我们可以实现一个队列。
生产者
RPUSH queue msg1
RPUSH queue msg2
消息进入队列。
消费者
LPOP queue
取出消息。
流程:
生产者 → RPUSH → Redis队列 → LPOP → 消费者
3 阻塞队列
普通队列有个问题:
如果队列为空
消费者要不断轮询
浪费 CPU。
Redis 提供:
BLPOP
BRPOP
作用:
如果队列为空
消费者阻塞等待
流程:
消费者等待
↓
生产者写入
↓
立即唤醒消费者
这就是 Redis 阻塞队列。
二、Redis 分布式锁如何实现?
1 为什么需要分布式锁?
在分布式系统中:
多个服务实例
同时操作同一资源
例如:
秒杀库存
如果没有锁:
库存可能被超卖
所以需要:
分布式锁
2 Redis 实现锁的核心
Redis 有一个关键能力:
命令是原子执行
我们可以使用:
SET key value NX EX
含义:
NX = key不存在才设置
EX = 过期时间
3 加锁流程
客户端执行:
SET lock_key uuid NX EX 10
意思:
如果锁不存在 → 创建锁
10秒自动过期
如果成功:
获得锁
如果失败:
说明别人已经加锁
4 为什么 value 要用 UUID?
因为释放锁时需要校验:
只有锁的拥有者才能删除锁
释放锁:
if value == uuid
DEL key
为了保证原子性,一般用 Lua脚本。
5 Redis 锁的问题
Redis 锁有一个经典问题:
主从切换
锁丢失
解决方案:
RedLock算法
即:
多个 Redis 节点同时加锁
多数成功才算成功
三、Redis 缓存击穿问题
缓存系统有三个经典问题:
缓存穿透 缓存击穿 缓存雪崩
这里重点讲 缓存击穿。
什么是缓存击穿?
场景:
某个热点数据:
key = product_100
有 10万请求/秒。
突然:
缓存过期
瞬间:
10万请求 → 数据库
数据库会被打爆。
这就是:
缓存击穿
解决方案1:互斥锁
流程:
请求发现缓存不存在
↓
获取分布式锁
↓
查询数据库
↓
写入缓存
↓
释放锁
其他线程:
等待缓存恢复
解决方案2:逻辑过期
缓存结构:
value + expireTime
流程:
缓存过期
↓
返回旧数据
↓
后台线程更新缓存
这样:
不会打爆数据库
四、Redis 事务实现原理
Redis 的事务非常特殊。
很多人误以为 Redis 事务和数据库一样。
其实不是。
Redis 事务核心命令:
MULTI
EXEC
流程:
MULTI
SET a 1
INCR a
EXEC
Redis 事务本质
Redis 事务:
命令队列
执行过程:
1 MULTI
2 命令进入队列
3 EXEC统一执行
流程:
客户端
│
MULTI
│
命令入队
│
EXEC
│
Redis顺序执行
Redis事务的特点
Redis 事务 不支持回滚。
原因:
Redis 设计目标是:
简单 + 高性能
而回滚会导致:
性能下降 实现复杂
所以 Redis 的事务保证:
命令顺序执行
但不保证:
失败回滚
五、如何查看 Redis 全量同步日志?
在 主从复制 时,会发生:
全量同步
流程:
Slave → Master 请求同步
Master → 生成RDB
发送给 Slave
如果你想查看日志,可以看 Redis 的日志文件。
常见位置:
/var/log/redis/redis.log
或者在 Redis 配置中:
logfile /var/log/redis.log
查看同步日志
可以使用:
grep SYNC redis.log
或者:
grep PSYNC redis.log
常见日志:
Full resync from master
Background saving started
Synchronization with slave succeeded
含义:
开始全量同步 生成RDB 同步成功
转载自CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/2501_92547326/article/details/158889383



