1. 分布式锁简介
1.1 简介
在分布式架构下,在 JVM 之间,使用分布式锁解决跨 JVM 进程的线程安全问题。
2. Redis 分布式锁分析
2.1 Redis 分布式锁原理
2.1.1 借助 setnx 和 expire 命令完成
2.1.2 原理解析
(1)key 不存在时创建,并设置 value 和过期时间,返回值为1;成功获取到锁
(2)key 存在时,直接返回0,获取锁失败
(3)持有锁的线程释放锁时,手动删除 key;或者过期时间到,key 自动删除,锁释放
2.1.3 加锁的问题
问题:setnx 成功,expire 失败,如果没有手动释放,锁永远被占用,其他线程永远抢不到锁
解决方案:
(1)使用 set 命令时,同时设置过期时间
(2)使用 lua 脚本,将加锁命令放在 lua 脚本中原子性的执行
2.2 Jedis 分布式锁实现
加锁:就是调用 SET key PX NX 命令
解锁:使用 lua 脚本
2.3 锁过期问题
解决方案:
(1)乐观锁方式,增加版本号
(2)watch dog 自动延期
3. Redisson 分布式锁
3.1 Redisson 简介
基于 Netty 的 Redis 客户端。能操作原生的 Redis 数据结构,提供了一系列具有分布式特性的工具类,实现了分布式锁。
3.2 Redisson 分布式锁
3.2.1 锁的存储结构
结构是 Hash:
key:锁的名字
字段:UUID + threadId
值:重入的次数
3.3 Watch Dog 自动延期
3.3.1 定义
当加锁成功后,同时开启守护线程,默认有效期是30秒,每隔10秒就会给锁续期到30秒
只有在未显式指定加锁时间时才会生效
lockWatchdogTimeout:可以设置超时时间
4. 分段锁
使用分段的方式(思想来源map/reduce,ConcurrentHashMap),以空间换时间。分别给不同的分段加锁,各个不同的分段可以同时进行操作。