基础知识
Redis 锁过期了会怎么样
- Redis 的 key 如果不设过期时间,并切不主动删除,那么这个 key 会一直存在。
- 那过期之后怎么处理 —> 过期策略
- 被动方式(惰性方式):访问的时候访问到过期的才删除。
- 主动方式:
- 定期删除:
- 定期在设置了过期时间的 key 中随机筛选 20 个;
- 删除其中已过期的 key;
- 如果过期 key 占比概率高过 25% 则继续重复前面步骤。
- 定时删除:
- 给 key 设置过期时间的时候同时设置一个定时器。
- 定期删除:
- Redis 是使用 惰性方式 和 定期方式 两种方式。
- 从节点不主动删除过期 key,而是等待主节点通过删除过期 key 时同步一个
del
指令给从节点,让从节点删除,
应用
Redis 解决重复消息
-
消息中间件是无法保证消息重复消费的,所以只能从业务上来保证消息不重复消费,在消费端保证接口的幂等性。
-
原理:你需要让生产者发送每条数据的时候,里面加一个全局唯一的 id,只要消费过该消息,就将id和消息数据写入redis,消费者开始消费前,先根据这个id查redis中有没有消费记录,消费过了,就别处理了,保证别重复处理相同的消息即可。
-
方法:使用 Redis 加锁机制
- 生产者向中间件发送消息时,里面加一个全局唯一的 id。
- 消费者消费前要使用就
SETNX
看返回值,查看redis 中有没有消费记录。- 返回值 1 表示设置 key 成功,表示没有消费过,可以进行处理;
- 返回值 0 表示设置 key 失败,表示已经消费过了。
-
隐患:
-
若第一个消费者在执行业务时,出现了死锁问题,或者宕机,那么 key 不会被删除,其他消费者会无法获取key的资源;
- 为此我们应该在将消息 id 放入Redis时,为它设置一个生存时间,也可以叫过期时间,避免在极端情况下的死锁问题。
-
加了过期时间,可能会存在锁被其他消费者释放的情况。(B锁被A删了)
-
问题在于 删除 key 没有判断这个锁是属于谁的。
A 获得 锁
A 执行
A 锁过期 (删除了 key)
B 获得锁 (又 set 了 key)
B 执行
(A 执行)
A del 删除key
-
那么可以在删除锁的时候判断这个锁是否属于这个消费者。(用LUA脚本)
-
-
锁过期了,业务还没执行完。(类似于第二种情况)
-
-
Redis 加锁机制有很多方法,看分布式锁部分,可以看到有很多实现方法。
Redis 实现分布式锁
- 分布式锁,RedisLock:面试官:你真的了解Redis分布式锁吗?
- Redis 实现分布式锁