zookeeper 分布式锁原理(分布式锁实现原理)

Zookeeper分布式锁的原理问:在什么样的场景下我们需要使用Zookeeper分布式锁呢?在分布式的项目中,指定的项目我们需要使用到锁的机制,但是在分布式下我们使用的内存锁都是相对独立的,因为每一个项目都有一个自己的JVM,而我们使用java类的锁都是受JVM控制的,这样在两台真实服务器上调用同一把锁的时候是没有办法进行锁操作,这个是我们就需要用到Zookeeper分布式锁了。…

大家好,又见面了,我是你们的朋友全栈君。

Zookeeper分布式锁的原理

问:在什么样的场景下我们需要使用Zookeeper分布式锁呢?

    在分布式的项目中,指定的项目我们需要使用到锁的机制,但是在分布式下我们使用的内存锁都是相对独立的,因为每一个项目都有一个自己的JVM,而我们使用java类的锁都是受JVM控制的,这样在两台真实服务器上调用同一把锁的时候是没有办法进行锁操作,这个是我们就需要用到Zookeeper分布式锁了。

 

问:什么是Zookeeper分布式锁的节点zndoe?

    这里我们在处理业务时候统一使用Zookeeper的锁,我们需要在调用Zookeeper锁之前创建一个节点命名空间(节点称为znode),每个节点都用一个以斜杠(/)分隔的路径表示,而且每个节点都有父节点(根节点除外),非常类似于文件系统。例如,/foo/mylock这个表示一个znode,它的父节点为/foo,父父节点为/,而/为根节点没有父节点。与文件系统不同的是,这些节点都可以设置关联的数据,而文件系统中只有文件节点可以存放数据而目录节点不行。Zookeeper为了保证高吞吐和低延迟,在内存中维护了这个树状的目录结构,这种特性使得Zookeeper不能用于存放大量的数据,每个节点的存放数据上限为1M。

    如图:

zookeeper 分布式锁原理(分布式锁实现原理)

问:Zookeeper分布式锁是如何保证高可用的?

    为了保证高可用,zookeeper需要以集群形态来部署,集群的数量一定要为奇数,因为Zookeeper的选举机制集群的数量不能为偶数。这样只要集群中大部分机器是可用的(能够容忍一定的机器故障),那么zookeeper本身仍然是可用的。客户端在使用zookeeper时,需要知道集群机器列表,通过与集群中的某一台机器建立TCP连接来使用服务,客户端使用这个TCP链接来发送请求、获取结果、获取监听事件以及发送心跳包。如果这个连接异常断开了,客户端可以连接到另外的机器上。

客户端的读请求可以被集群中的任意一台机器处理,如果读请求在节点上注册了监听器,这个监听器也是由所连接的zookeeper机器来处理。对于写请求,这些请求会同时发给其他zookeeper机器其他机器会转发给leader由leader统一操作写操作,leader完成后请求才会返回成功。

因此,随着zookeeper的集群机器增多,读请求的吞吐会提高但是写请求的吞吐会下降。有序性zookeeper中非常重要的一个特性,所有的更新都是全局有序的,每个更新都有一个唯一的时间戳,这个时间戳称为zxid(Zookeeper Transaction Id)。而读请求只会相对于更新有序,也就是读请求的返回结果中会带有这个zookeeper最新的zxid。

问:Zookeeper如何实现分布式锁的?

在描述算法流程之前,先看下zookeeper中几个关于节点的有趣的性质:

有序节点:假如当前有一个父节点为/lock,我们可以在这个父节点下面创建子节点;zookeeper提供了一个可选的有序特性,例如我们可以创建子节点“/lock/node-”并且指明有序,那么zookeeper在生成子节点时会根据当前的子节点数量自动添加整数序号,也就是说如果是第一个创建的子节点,那么生成的子节点为/lock/node-0000000000,下一个节点则为/lock/node-0000000001,在下一个节点是/lock/node-0000000002,依次类推。

临时节点:客户端可以建立一个临时节点,在会话结束或者会话超时后,zookeeper会自动删除该节点。

事件监听:在读取数据时,我们可以同时对节点设置事件监听,当节点数据或结构变化时,zookeeper会通知客户端。当前zookeeper有如下四种事件:1)节点创建;2)节点删除;3)节点数据修改;4)子节点变更。

下面描述使用zookeeper实现分布式锁的算法流程,假设锁空间的根节点为/lock:

1.客户端连接zookeeper,并在/lock下创建临时的且有序的子节点,第一个客户端对应的子节点为/lock/lock-0000000000,第二个为/lock/lock-0000000001,以此类推。

2.客户端获取/lock下的子节点列表,判断自己创建的子节点是否为当前子节点列表中序号最小的子节点,如果是则认为获得锁,否则监听/lock的子节点变更消息,获得子节点变更通知后重复此步骤直至获得锁;

3.执行业务代码;

4.完成业务流程后,删除对应的子节点释放锁。

注意:步骤1中创建的临时节点能够保证在故障的情况下锁也能被释放,考虑这么个场景:假如客户端a当前创建的子节点为序号最小的节点,获得锁之后客户端所在机器宕机了,客户端没有主动删除子节点;如果创建的是永久的节点,那么这个锁永远不会释放,导致死锁;由于创建的是临时节点,客户端宕机后,过了一定时间zookeeper没有收到客户端的心跳包判断会话失效,将临时节点删除从而释放锁。

业务流程如图:

zookeeper 分布式锁原理(分布式锁实现原理)

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/128538.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Flask 让jsonify返回的json串支持中文显示

    Flask 让jsonify返回的json串支持中文显示用flask时遇到了返回字符串支持中文显示的问题,在web端显示的是utf-8的编码,而不是中文,如下图。虽然不影响接口的读取,但是可读性太差,于是研究了一下怎么直接显示成中文。最后找到了解决方案如下,在配置中加入下面一行代码就OK了。app.config[‘JSON_AS_ASCII’]=Falsejson.dumps()解决同样的问题可以加入ensure_ascii=False参考资料:

    2022年5月23日
    34
  • Slog53_Unity3D之功能脚本_FindOtherGameObjects_找到场景内除自己外的其他GameObject

    Slog53_Unity3D之功能脚本_FindOtherGameObjects_找到场景内除自己外的其他GameObject

    2021年6月12日
    107
  • phantomjs 简介「建议收藏」

    phantomjs 简介「建议收藏」在爬虫、自然语言处理群320349384中的交流中,偶然接触到phantomjs、casper等相对于httpclient较新的框架及采集解决方案,微查之后发现方案可行,故尽清明三日之力,将其二次开发应用于百度元搜索信息采集项目中,达到预期效果,下一步将重点应用到腾讯微博采集和抢票抢手机项目中。下面,将分步骤介绍一下。  一、phantomjs介绍   (1)一个基于web

    2022年7月26日
    11
  • 数据库导入sql文件_mysql导入sql文件命令

    数据库导入sql文件_mysql导入sql文件命令Sql文件导入数据库-保姆级教程,铁打的保姆,希望对大家能有所帮助,不要忘了点赞+收藏哦

    2022年10月2日
    3
  • 開發中的DEV,QAS,UAT,PRD是什麼意思

    開發中的DEV,QAS,UAT,PRD是什麼意思IDES:InternetDemonstrationandEvaluationSystem交互式演示与评估系统DEV:DevelopmentSystem,开发系统QAS:QualityAssuranceSystem,质量保证系统UAT:UserAcceptanceTest用户验收测试PRD:ProductionSystem,生产系统…

    2022年6月28日
    56
  • 中标麒麟7.0+linux内核版本,中标麒麟7.0下载

    中标麒麟7.0+linux内核版本,中标麒麟7.0下载中标麒麟v7.064位系统是由我国自主研发的一款电脑上使用的linux操作系统,这款电脑系统在经过大量的试验和改进之后,现在的体验是非常不错的,而且性能一级棒,欢迎有兴趣的用户来IT猫扑下载。中标麒麟7.0安装教程1、首先到本页下载中标麒麟7.064位系统,由于系统是iso格式的镜像文件,因此需要通过刻录软件将系统刻录到光盘再进行安装2、插入已刻录“中标麒麟桌面操作系统”的系统光盘,并设置电脑…

    2022年10月21日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号