在分布式系统中,分布式锁是为了解决多实例之间的同步问题。例如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的分布式锁
简介: 有一类写多读少的业务场景:大部分请求是对数据进行修改,少部分请求对数...
本文转载自微信公众号「后端技术指南针」,作者程序员大白啊 。转载本文请联系后...
美国服务器租用已经不是刚刚兴起的业务,对于国内企业用户来讲,至少也有15年的...
随着虚拟技术的不断成熟,服务器租用在全球的热度日益高涨。虽然国内服务器技术...
在过去的20年中,Progressive雇用了70至90名夏季IT实习生,这些实习生从5月至8月...
在 Node.js 中开启一个 HTTP 服务很简单,如果想使用 Node.js 开启一个 HTTPS 的...
做网站懒得备案,选国外云服务器就能解决这个问题,那么 国外云服务器哪家好 呢?...
许多组织都在努力从分析中获取业务价值。Gartner的调查称,到2022年,只有20%的...
服务网格(Service Mesh)为服务通信带来了安全性、弹性、可见性,因此使开发人员...
Nginx 是一个采用主从架构的 Web 服务器,可用于反向代理、负载均衡器、邮件代理...