Redis分布式锁
「这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战」
使用场景
在同一个JVM内部,大家往往采用synchronized或者Lock的方式来解决多线程间的安全问题,但是在分布式架构下,在JVM之间,那么就需要一种更加高级的锁机制,来处理种跨JVM进程之间的线程安全问题,解决方案就是:使用分布式锁。
分布式锁一般有如下特征
- 互斥性: 同一时刻只能有一个线程持有锁
- 重入性: 同一节点上的同一个线程如果获取了锁之后能够再次获取锁
- 锁超时:和J.U.C中的锁一样支持锁超时,防止死锁
- 能够及时从阻塞状态中被唤醒
Redis分布式锁原理
Redis分布式锁机制,主要借助setnx和expire两个命令完成
- setnx---当key不存在,将key设置为value,存在不做任何操作,返回0
- expire---设置key过期时间
原理解析
- key不存在时创建,并设置value和过期时间,返回值为1;成功获取到锁
- 如key存在时直接返回0,抢锁失败
- 持有锁的线程释放锁时,手动删除key;或者过期时间到,key自动删除,锁释放
Redis加锁问题
setnx成功
expire失败,如果没有收到释放,那么这个锁永远被占用,其他线程永远也抢不到锁
解决方法
- 使用set命令时,同时设置过期时间
- 使用lua脚本,将加锁的命令放在lua脚本中原子性的执行
加锁命令
调用SET key PX NX命令
set key value [EX seconds] [PX milliseconds] [NX|XX]
锁过期问题
解决方法:
- 乐观锁方式,增加版本号
- watch dog自动延期