为什么需要分布式锁
单进程的程序,如果有多线程并且对共享资源进行抢夺的情况,我们会使用单机锁,但是随着业务的发展,或者架构的升级。往往会有多个进程,他们也可能是分布在各个机器环境上。所以我们需要一个分布式锁。
如何实现分布式锁
- 需要有单机锁的特性—>互斥
- 可以释放锁—>不能死锁
- 需要有一个外部系统来实现—>分布式
分布式锁安全吗
- 如何保证不死锁?
主动释放锁,设置过期时间
- 如何让分布式锁本身是安全的?
- 保证锁的可靠性,部署集群
- 并且加锁和释放锁要用原子操作
- 如何保证不会释放别人的锁?
设置一个唯一标识,uuid或者线程号
- 过期时间如何评估?
加锁时,可以设置过期时间,然后开启一个守护线程,定时检测锁的失效时间,如果快到期了还没完成对共享资源的操作,就进行续期。可以采用redisson(SDK)的看门狗,进行锁续期。
什么是redlock
单机的分布式锁是不可靠的,集群一般采用主从集群+哨兵模式。但是主从复制时异步的,可能在同步消息的过程中,主节点宕机,造成锁消息丢失。
为此,redis的作者提出了redlock。
- 不部署从库和哨兵,只需要部署主库
- 但是主库需要部署多个,推荐5个
不是部署 Redis Cluster,就是部署 5 个简单的 Redis 实例。
RedLock的流程
- 需要加锁的客户端先获取当前时间戳T1
- 客户端依次向这5个(所有)实例发送加锁请求。并且请求设置超时时间(远小于锁的有效时间),过时间没加锁就认为失败,立即向下一个redis示例申请加锁
- 如果大于半数(3)的实例加锁成功,并且获取当前时间戳T2。T2-T1>TTL,认为加锁成功
- 加锁成功,操作共享资源
- 加锁失败,执行lua脚本向所有节点释放锁