最近完成毕设过程中对 redis 锁有所了解,随后呢想到著名的分布式锁 zk
为了巩固自己的知识领域,为此写这么一篇小文章
Redis 实现分布式锁
1.根据 lockKey 区进行 setnx(set not exist,如果 key 值为空,则正常设置,返回 1,否则不会进行设置并返回 0)操作,如果设置成功,表示已经获得锁,否则并没有获取锁。 2.如果没有获得锁,去 Redis 上拿到该 key 对应的值,在该 key 上我们存储一个时间戳(用毫秒表示,t1),为了避免死锁以及其他客户端占用该锁超过一定时间(5 秒),使用该客户端当前时间戳,与存储的时间戳作比较。 3.如果没有超过该 key 的使用时限,返回 false,表示其他人正在占用该 key,不能强制使用;如果已经超过时限,那我们就可以进行解锁,使用我们的时间戳来代替该字段的值。 4.但是如果在 setnx 失败后,get 该值却无法拿到该字段时,说明操作之前该锁已经被释放,这个时候,最好的办法就是重新执行一遍 setnx 方法来获取其值以获得该锁。
释放锁:删除 redis 中 key
Zookeeper 实现分布式锁
基于临时顺序节点: 1.客户端调用 create()方法创建名为“locknode/guid-lock-”的节点,需要注意的是,这里节点的创建类型需要设置为 EPHEMERAL_SEQUENTIAL。 2.客户端调用 getChildren(“locknode”)方法来获取所有已经创建的子节点。 3.客户端获取到所有子节点 path 之后,如果发现自己在步骤 1 中创建的节点是所有节点中序号最小的,那么就认为这个客户端获得了锁。 4.如果创建的节点不是所有节点中序号最小的,那么则监视比自己创建节点的序列号小的最大的节点,进入等待。直到下次监视的子节点变更的时候,再进行子节点的获取,判断是否获取锁。
释放锁的过程相对比较简单,就是删除自己创建的那个子节点即可。
总结
redis 分布式锁,其实需要自己不断去尝试获取锁,比较消耗性能
zk 分布式锁,获取不到锁,注册个监听器即可,不需要不断主动尝试获取锁,性能开销较小
另外一点就是,如果是 redis 获取锁的那个客户端 bug 了或者挂了,那么只能等待超时时间之后才能释放锁;而 zk 的话,因为创建的是临时 znode,只要客户端挂了,znode 就没了,此时就自动释放锁
由于自己资金有限,毕设项目 redis 先行。
若有收获,就点个赞吧