Redis08-01分布式锁

分布式锁的核心是实现多进程之间互斥,而满足这一点的方式有很多,常见的有三种:

MySQL Redis Zookeeper
互斥 利用mysql本身的互斥锁机制 利用setnx这样的互斥命令 利用节点的唯一性和有序性实现互斥
高可用
高性能 一般 一般
安全性 断开连接,自动释放锁 利用锁超时时间,到期释放 临时节点,断开连接自动释放

注意redis的超时释放

Redis08-01分布式锁2

Redis08-01分布式误删2

解决方法:释放锁的时候判断一下锁标识

Redis08-01分布式误删解决

Redis08-02分布式锁原子性

==使用Redis事务(Redis只保证了原子性,不能保证一致性,要不然再加上乐观锁进行判断,复杂==

==使用简单的Lua脚本,在一个脚本中编写多条Redis命令,确保多条命令执行时的原子性。==

样例:

Redis08-03调用脚本

Redis08-04Lua

-- 比较标识的一致性
if(redis.call('get', KEYS[1]) == ARGV[1]) then
-- 释放锁
redis.call('del', key)
end
return 0

Redis08-lua

基于Redis的分布式锁实现思路:

  • 利用set nx ex获取锁,并设置过期时间,保存线程标示
  • 释放锁时先判断线程标示是否与自己一致,一致则删除锁

特性:

  • 利用set nx满足互斥性
  • 利用set ex保证故障时锁依然能释放,避免死锁,提高安全性·利用Redis集群保证高可用和高并发特性

Redsson可重入锁

==基于setnx存在以下问题==

  • 不可重入:同一个线程无法多次获取同一把锁

  • 不可重试:获取锁只尝试一次就返回false,没有重试机制

  • 锁超时释放虽然可以避免死锁,但如果是业务执行耗时较长,也会导致锁释放,存在安全隐患

  • 如果Redis提供了主从集群,主从同步存在延迟,当主宕机时,如果从并同步主中的锁数据,则会出现锁实现

Redis08-Redission简单的用法

可重入原理

Redis08-Redission可重入原理

Redis08-Redission加锁

Redis08-Redission解锁

Redis08-Redission分布式锁原理

Redisson分布式锁原理:

  • 可重入:利用hash结构记录线程id和重入次数
  • 可重试:利用信号量和PubSub功能实现等待、唤醒,获取锁失败的重试机制
  • 超时续约:利用watchDog,每隔一段时间( releaseTime / 3),重置超时时间