redission锁:
上锁过程:
redission1客户端去hexists判断是否可以获取锁,可以就执行lua脚本,为redission1客户端绑定分布式锁lck_acc_000。此时lck_acc_000的value设置为Hash类型,key为redission1客户端标识,map组成为key(标识)和value(锁的次数)组成。然后lck_acc_000默认国企时间为30秒。
redission2客户端去执行hexists判断是否能获取lck_acc_000锁,此时已被redission1客户端持有,不能获取,也就是不能加锁,返回pttl lck_acc_000,然后redission2客户端可以通过获取锁的过期时间来设置下一次访问时间。
lck_acc_000默认30秒过期,redission提供看门狗机制进行锁时间的续期。当客户端加锁成功后,会启动watch dog每10秒为redission1客户端查询是否正在进行工作,如果还未完成工作,就会进行锁时间续期,如果不工作,会将锁释放掉。
释放锁过程:
redission锁使用的是可重入锁,就是可以多次持有锁。
如果redission客户端多次持有锁,就是将锁key的值hash的值的次数每次加1。
释放锁就是hash值得次数减1。为0将锁删掉,真正意义上释放。
redis锁:
redis锁使用得自身的setnx机制,开启事务之后,将key使用setnx上锁,如果key存在会进行上锁。setnx意思是如果key不存在则创建。然后在事务提交之后将锁删掉就行。
在java代码中就是如果key存在,给key添加一个锁,然后事务处理结束之后,自己在进行unlock释放锁。
分布式锁会存在一个问题:
当缓存服务器集群部署之后,在业务使用过程中会有一个主节点服务器,然后通过主节点同其他节点缓存服务器进行数据同步,中间存在时间差。当客户端1在主节点服务器进行持有锁操作之后,主节点服务器在与次节点服务器数据同步时宕机了,数据未同步过去,此时缓存服务器会切换为次节点服务器,此时客户端2就也能持有锁。就出现了锁被多服务持有,出现了原子性被破坏。