Redis单点方式:html
首先,Redis客户端为了获取锁,向Redis节点发送以下命令:node
SET resource_name my_random_value NX PX 30000
上面的命令若是执行成功,则客户端成功获取到了锁,接下来就能够访问共享资源了;而若是上面的命令执行失败,则说明获取锁失败。redis
注意,在上面的SET
命令中:算法
my_random_value
是由客户端生成的一个随机字符串,它要保证在足够长的一段时间内在全部客户端的全部获取锁的请求中都是惟一的。NX
表示只有当resource_name
对应的key值不存在的时候才能SET
成功。这保证了只有第一个请求的客户端才能得到锁,而其它客户端在锁被释放以前都没法得到锁。PX 30000
表示这个锁有一个30秒的自动过时时间。固然,这里30秒只是一个例子,客户端能够选择合适的过时时间。最后,当客户端完成了对共享资源的操做以后,执行下面的Redis Lua脚原本释放锁:数据库
if redis.call("get",KEYS[1]) == ARGV[1] then return redis.call("del",KEYS[1]) else return 0 end
这段Lua脚本在执行的时候要把前面的my_random_value
做为ARGV[1]
的值传进去,把resource_name
做为KEYS[1]
的值传进去。服务器
总结:dom
1.必须设置过时时间,过时时间须要谨慎考虑,过短锁没等主动释放就过时,太长一旦拥有锁的对象出现问题,别人会很长时间没法使用。异步
2.setnx 和 过时时间必须是原子的分布式
3.value必须是随机的,保证解铃还须系铃人,别人解不了post
4.释放必须用Lua原子方式进行。由于Get和Del是分布进行的,没发指定删除随机value的key,因此必须原子性,防止删除的时候不是本身的锁,而是过时后别人加上去的锁。
另外:单机的问题没法达到高可用,当redis宕了后,锁失效,经过slave方式处理也可能会有1s内的数据同步问题,若是正好遇上master上加上锁,还没同步到slave上,master宕,slave变成master时锁不对。
多redis集群方式:(客户端须要作的事情太多,不太好用仍是用zk吧)
考虑:若是Client1 获取lock1后,执行了Full GC,到了过时时间,lock1过时。Client2获取lock2,执行数据操做。Client1恢复运行,执行数据操做!这样两个Client同时拿到了锁。
可让Lock Server在分配锁的时候返回一个递增数字,在执行数据操做的时候,须要提交这个数字,记录最后一次执行的数字,而且只接受比这个数字大的请求。保证请求数据操做的Client是按拿到锁的顺序执行的。但redis暂时不能返回这个数字。
使用分布式锁的方式有两种状况:
结论:
http://zhangtielei.com/posts/blog-redlock-reasoning.html
一个基于ZooKeeper构建分布式锁的描述(固然这不是惟一的方式):
/lock
。那么第一个客户端就建立成功了,至关于拿到了锁;而其它的客户端会建立失败(znode已存在),获取锁失败。看起来这个锁至关完美,没有Redlock过时时间的问题,并且能在须要的时候让锁自动释放。但仔细考察的话,并不尽然。
ZooKeeper是怎么检测出某个客户端已经崩溃了呢?实际上,每一个客户端都与ZooKeeper的某台服务器维护着一个Session,这个Session依赖按期的心跳(heartbeat)来维持。若是ZooKeeper长时间收不到客户端的心跳(这个时间称为Sesion的过时时间),那么它就认为Session过时了,经过这个Session所建立的全部的ephemeral类型的znode节点都会被自动删除。
设想以下的执行序列:
/lock
,得到了锁。/lock
被自动删除。/lock
,从而得到了锁。最后,客户端1和客户端2都认为本身持有了锁,冲突了。这与以前Martin在文章中描述的因为GC pause致使的分布式锁失效的状况相似。
ZooKeeper的watch机制。这个机制能够这样来使用,好比当客户端试图建立/lock
的时候,发现它已经存在了,这时候建立失败,但客户端不必定就此对外宣告获取锁失败。客户端能够进入一种等待状态,等待当/lock
节点被删除的时候,ZooKeeper经过watch机制通知它,这样它就能够继续完成建立操做(获取锁)。这可让分布式锁在客户端用起来就像一个本地的锁同样:加锁失败就阻塞住,直到获取到锁为止。这样的特性Redlock就没法实现。
小结一下,基于ZooKeeper的锁和基于Redis的锁相比在实现特性上有两个不一样:
http://zhangtielei.com/posts/blog-redlock-reasoning-part2.html