在分布式系统中,分布式锁是为了解决多实例之间的同步问题。例如master选举,可以获取分布式锁的就是master,获取失败的就是slave。又或者可以获取锁的实例可以完成特定的操做。redis
目前比较经常使用的分布式锁实现有两种,基于zookeeper实现和基于redis实现。zookeeper和redis也是生产环境中常常用到的第三方组件。下面我会分析它们的实现原理。算法
分布式锁实现要求安全
实现一个分布式锁至少要知足下面三点要求:网络
zookeeper分布式锁dom
在讲解zookeeper的分布式锁以前有两个概念须要明确:异步
zookeeper的分布式锁实现原理就是利用临时顺序节点,大概流程为:分布式
例如,对于加锁过程,全部的客户端都在/lock目录下面建立临时节点,若是发现本身建立的临时节点是/lock目录中最小的节点,那么就获取锁成功,不然就watch比本身小的节点中的最大节点。性能
监控比本身小的节点中的最大节点是为了不“惊群”效应,避免一个锁释放把全部等待的客户端唤醒,可是只有一个客户端能获取锁。大数据
对于释放锁,只须要把本身建立的临时顺序节点删除便可。整个过程流程图以下:cdn
优势:锁安全性高,zookeeper数据不易丢失。用户使用简单。
缺点:性能消耗比较高。由于须要动态产生和删除临时节点,当集群负载比较高时临时节点消失会有时间差(通常在一分钟范围内)。
redis分布式锁
redis的分布式锁实现比zookeeper分布式锁实现复杂,也分为redis单实例和多实例(master-master)实现方式。
须要特别指出的是redis若是是master-slave这种结构部署时,获取和释放锁都只能向master请求,和单实例的实现原理基本同样,不然主从切换时会出现多人拿到同一把锁的状况。
例如:
redis单实例实现方案
经过下面命令得到锁:
SET resource_name my_random_value NX PX 30000
这个命令的做用是只有这个key不存在时才会设置这个key的值(NX的做用,即not exist),超时时间设置为30000毫秒(PX的做用),这个key的值设置为my_random_value。这个值必须在全部获取锁请求的客户端里面保持惟一。
key值的超时时间,也叫作“锁有效时间”。这是锁的自动释放时间。
这套实现方案在非分布式的、单点的、保证永不宕机的环境是适用的。
redis集群实现方案(Redlock算法)
在分布式版本的算法里咱们假设有N个redis master节点,这些节点彻底独立,不用任何的复制或者分布式协调算法来同步数据。
这里假设N=5,一个客户端获取锁的过程以下:
获取锁成功的节点数须要超过master节点数量的一半才认为是获取锁成功的思路应该是借鉴了zookeeper的paxos算法。
还有一个须要指出的点是,当一个客户端获取失败时应该随时延时后再进行重试,避免多个客户端同时重试又同时失败。
优势:性能高
缺点:单实例会有单点问题,多实例主从切换会致使数据丢失,master-master集群模式实现复杂。
看大佬给你讲解基于Zookeeper、Redis的分布式锁