4、使用set下令加锁并设置锁逾期时间:
下令格式:set <lock.key> <lock.value> nx ex <expireTime>
详情参考redis使用文档:http://doc.redisfans.com/string/set.html (1)存在标题:
① 如果线程A乐成得到了锁,而且设置的超时时间是 30 秒。如果某些缘故原由导致线程 A 实行<typo id="typo-3121" data-origin="的" ignoretag="true">的</typo>很慢,过了 30 秒都没实行完,这时间锁逾期主动开释,线程 B 得到了锁。
② 随后,线程A实行完使命,接着实行del指令来开释锁。但这时间线程 B 还没实行完,线程A现实上删除的是线程B加的锁。 (2)办理方案:
可以在 del 开释锁之前做一个判断,验证当前的锁是不是本身加的锁。在加锁的时间把当前的线程 ID 当做value,并在删除之前验证 key 对应的 value 是不是本身线程的 ID。但是,如许做实在隐含了一个新的标题,get操纵、判断和开释锁是两个独立操纵,不是原子性。对于非原子性的标题,我们可以使用Lua脚原来确保操纵的原子性 5、锁续期:(这种机制类似于redisson的看门狗机制,文章背面会具体阐明)
虽然步调4制止了线程A误删掉key的情况,但是同一时间有 A,B 两个线程在访问代码块,仍旧是不完善的。怎么办呢?我们可以让得到锁的线程开启一个保卫线程,用来给快要逾期的锁“续期”。
① 假设线程A实行了29 秒后还没实行完,这时间保卫线程会实行 expire 指令,为这把锁续期 20 秒。保卫线程从第 29 秒开始实行,每 20 秒实行一次。
② 情况一:当线程A实行完使命,会显式关掉保卫线程。
③ 情况二:如果服务器忽然断电,由于线程 A 和保卫线程在同一个历程,保卫线程也会停下。这把锁到了超时的时间,没人给它续命,也就主动开释了。
a. 对key不设置逾期时间,由Redisson在加锁乐成后给维护一个watchdog看门狗,watchdog负责定时监听并处置惩罚,在锁没有被开释且快要逾期的时间主动对锁举行续期,包管解锁前锁不会主动失效
b. 通过Lua脚本实现了加锁息争锁的原子操纵
c. 通过记载获取锁的客户端id,每次加锁时判断是否是当前客户端已经得到锁,实现了可重入锁。