分布式锁
Set [key] [value] ex [xx] nx
- 简单业务中使用
- 存在锁续期问题
单机Redis实现:Redisson
概述
- 基于lua脚本,原子性
- Redis官方推荐
加锁机制
- 判断是否存在锁
- 若无则
hincrby myLock 285475da-9152-4c83-822a-67ee2f116a79:52 1
- 若存在锁,则进入互斥机制
锁互斥机制
- 客户端获取锁不成功,则会返回锁的TTL
- 通过Redis的发布订阅机制订阅锁释放
- 超过最大等待时间则返回获取锁失败
watch dog机制
- 默认加锁时间为30秒则启用watch Dog
1 2
watch dog原理: 成功启动watch dog的线程,会将线程id放到一个列表中,定时判断线程是否存活,然后给锁续期
可重入机制
1 2 3
127.0.0.1:6379> HGETALL myLock 1) "285475da-9152-4c83-822a-67ee2f116a79:52" 2) "2"
- value值加1
锁释放机制
- 删除锁
- 发送释放锁消息
- 删除watch dog
如何防死锁
- 给key设置过期时间
如何保证加锁解锁是同一个线程
- 指定一个key为锁的标记,值为线程id
锁续期问题
- 通过watch dog
优点
- 性能优
- 可重入
- 支持续期(watch dog)
- Redis的订阅发布,优化等待锁线程流程
缺点
Redis Master-Slave 架构,master宕机后,锁没有同步到slave,则会出现多个客户端同时加锁
1 2 3
解决: 1、选举成master后,在TTL后才提供加锁服务 2、用Redlock
多机Redis实现:Redlock
- redlock算法流程
- 1、获取当前时间戳
- 2、依次重各个master获取锁,获取锁的超时时间远小于TTL
- 3、获取到n/2+1个锁后才算是获取锁成功
- 4、锁的实际有效时间:TTL-获取所有用时-时钟偏移
- 5、若中途获取锁失败,则需要删除已经获取成功的锁
- 如何防锁
- 设置过期时间
- 如何保证加锁解锁是同一个线程
- 指定一个key为锁的标记,值为线程id
- 锁续期问题
- 结合redisson
- 优点
- 缺点
参考
- redisson:https://zhuanlan.zhihu.com/p/135864820
- redlock:https://www.cnblogs.com/rgcLOVEyaya/p/RGC_LOVE_YAYA_1003days.html
This post is licensed under CC BY 4.0 by the author.