在分布式系统中,数据手把手带实现锁分布式锁是大佬的分为了解决多实例之间的同步问题。例如master选举,基于能够获取分布式锁的布式就是master,获取失败的数据手把手带实现锁就是slave。又或者能够获取锁的大佬的分实例能够完成特定的操作。 目前比较常用的基于分布式锁实现有两种,基于zookeeper实现和基于redis实现。布式zookeeper和redis也是数据手把手带实现锁生产环境中经常用到的第三方组件。下面我会分析它们的大佬的分实现原理。 分布式锁实现要求 实现一个分布式锁至少要满足下面三点要求: zookeeper分布式锁 在讲解zookeeper的分布式锁之前有两个概念需要明确: zookeeper的分布式锁实现原理就是利用临时顺序节点,大概流程为: 例如,对于加锁过程,所有的客户端都在/lock目录下面创建临时节点,如果发现自己创建的临时节点是/lock目录中最小的节点,那么就获取锁成功,否则就watch比自己小的节点中的最大节点。 监控比自己小的云服务器提供商节点中的最大节点是为了避免“惊群”效应,避免一个锁释放把所有等待的客户端唤醒,但是只有一个客户端能获取锁。 对于释放锁,只需要把自己创建的临时顺序节点删除即可。整个过程流程图如下: 优点:锁安全性高,zookeeper数据不易丢失。用户使用简单。 缺点:性能消耗比较高。因为需要动态产生和删除临时节点,当集群负载比较高时临时节点消失会有时间差(一般在一分钟范围内)。 redis分布式锁 redis的分布式锁实现比zookeeper分布式锁实现复杂,也分为redis单实例和多实例(master-master)实现方式。 需要特别指出的是redis如果是master-slave这种结构部署时,获取和释放锁都只能向master请求,和单实例的实现原理基本一样,否则主从切换时会出现多人拿到同一把锁的情况。 例如: 客户端A在master拿到了锁。 master节点在把A创建的key写入slave之前宕机了。(主从同步是异步操作) slave变成了master节点。源码下载 B也得到了和A还持有的相同的锁,因为slave还没有A持有锁的信息。 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的分布式锁