| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> Zookeeper-应用-分布式锁以及和Redis实现对比 -> 正文阅读 |
|
[大数据]Zookeeper-应用-分布式锁以及和Redis实现对比 |
系列文章目录?认识 Zookeeper -基本概念,组成和功能_小王师傅66的博客-CSDN博客 zookeeper-集群-选举机制_小王师傅66的博客-CSDN博客 ZooKeeper-集群-ZAB协议与数据同步_小王师傅66的博客-CSDN博客 目录 前言????????因为分布式锁在分布式系统中非常重要,所以把分布式锁的实现从ZooKeeper应用中单独拿出来讲。 ? ? ? ? 关于第二节ZooKeeper实现分布式锁的部分,主要借鉴的《从Paxos到Zookeeper(分布式一致性原理与实践)》—倪超 一书。结合我个人的理解,对内容有所精简。大家如果想了解更细节的内容,可以自行阅读这本书,书中还讲解了ZooKeeper在阿里巴巴的实践与应用,个人觉得不仅能加深对ZooKeeper的认识,还能扩宽知识面。相见恨晚!!!墙裂推荐!!!!为作者打Call 一、分布式锁是什么?????????分布式锁是控制分布式系统之间同步访问共享资源的一种方式。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要通过一些互斥手段来防止彼此之间的干扰,以保证一致性,在这种情况下,就需要使用分布式锁了。 (大家可以先看下面的流程图,再来看文字解说) 二、ZooKeeper实现分布式锁1.排它锁
?????????排他锁(Exclusive Locks, 简称X锁),又称为写锁或独占锁,是一种基本的锁类型。如果事务T1对数据对象O1加上了排他锁,那么在整个加锁期间,只允许事务T对O1进行读取和更新操作,其他任何事务都不能再对这个数据对象进行任何类型的操作,直到T1释放了排他锁。 ?1.1定义锁????????通过ZooKeeper上的数据节点来表示一个锁 ,例如/exclusive_ lock/lock节点就可以被定义为一个锁,如图所示 ? 1.2 获取锁????????在需要获取排他锁时,所有的客户端都会试图通过调用create()接口, 在/exclusive_ lock 节点下创建临时子节点/exclusive_ lock/lock,在所有的客户端中,最终只有一个客户端能够创建成功,那么就可以认为该客户端获取了锁。同时,所有没有获取到锁的客户端就需到/exclusive_lock节点上注册一个子节点变更的Watcher监听,以便实时监听到lock节点的变更情况。 1.3 释放锁????????/exclusive_ lock/lock 是一个临时节点,因此在以下两种情况下,都有可能释放锁。 ? 2.共享锁?????????共享锁(Shared Locks,简称S锁),又称为读锁,同样是一种基本的锁类型。如果事务T对数据对象O加上了共享锁,那么当前事务只能对O进行读取操作,其他事务也只能对这个数据对象加共享锁一直到该数据对象上的所有共享锁都被释放。 1.1 定义锁?????????和排他锁一样,同样是通过ZooKeeper上的数据节点来表示一个锁,是一个类似于 ???????? ? 1.2 获取锁????????在需要获取共享锁时,所有客户端都会到/shared_lock这个节点下面创建一个临时顺序节点,如果当前是读请求,那么就创建例如/shared_ lock/192.168.0.1-R-000000001的节点;如果是写请求,那么就创建例如/shared_ lock/192.168.0.1-W-0000000001的节点。 ?1.3 判断读写顺序????????根据共享锁的定义,不同的事务都可以同时对同一个数据对象进行读取操作,而更新操作须在当前没有任何事务进行读写操作的情况下进行。基于这个原则,我们来看看如何通ZooKeeper的节点来确定分布式读写顺序,大致可以分为如下4个步骤。 ????????2.确定自己的节点序号在所有子节点中的顺序。 ????????3.对于读请求: ????????4.接收到Watcher通知后,重复步骤1。 1.4 释放锁????????释放锁的逻辑和排他锁是一致的,这里不再赘述。整个共享锁的获取和释放流程,如图所示: ? (实在画不动了,把作者的图搬来了) ?羊群效应 ????????上面讲解的这个共享锁实现,大体上能够满足一般的分布式集群竞争锁的需求,并且性能都还可以。这里说的一般场景是指集群规模不是特别大,一般是在10台机器以内。但是如果机器规模扩大之后,会有什么问题呢? ????????当192.168.0.1 这台机器完成读操作后将节点/192.168.0.1- R-0000000001删除,余下的4台机器均收到了这个节点被移除的通知,然后重新从/shared_lock节点上获取一份新的子节点列表。每个机器判断自己的读写顺序。其中192.168.0.2这台机器检测到自己已经是序号最小的机器了,于是开始进行写操作,而余下的其他机器发现没有轮到自己进行读取或更新操作,于是继续等待。???????? ????????我们发现,第一个节点移除,只影响下一个节点,对剩下的节点没有影响,但却通知给了所有节点,对剩下的这些节点来说,这个事件通知跟自己是无关的。如果在集群规模比较大的情况下,不仅会对ZooKeeper服务器造成巨大的性能影响和网络冲击,更为严重的是,如果同一时间有多个节点对应的客户端完成事务或是事务中断引起节点消失,ZooKeeper服务器就会在短时间内向其余客户端发送大量的事件通知一这就是所谓的羊群效应。 ????????分布式锁竞争过程,它的核心逻辑在于:判断自己是否是所有子节点中序号最小的。于是,很容易可以联想到,解决羊群效应的关键是,每个节点对应的客户端只需要关注比自己序号小的那个相关节点的变更情况就可以了,而不需要关注全局的子列表变更情况。 ????????所以优化后的实现分布式锁的方案是: ????????1.客户端调用create()方法创建一个类似于“/shared_ lock/[Hostname]-请求类型-序号”的临时顺序节点。 改造后的共享锁流程图: ? (还是直接搬的作者的图)? ? ? ? ? 和我们实现多线程并发编程的逻辑相似,尽可能减小锁的粒度,提高系统的并发性能。但很明显,改造后的实现流程比改造前复杂了,在实际实现过程中,大家可以根据业务场景和集群规模来选择适合自己的分布式锁实现:在集群规模不大、网络资源丰富的情况下,第一种分布式锁实现方式是简单实用的选择;而如果集群规模达到一定程度,并且希望能够精细化地控制分布式锁机制,那么不妨试试改进版的分布式锁实现。 三、ZooKeeper与Redis实现分布式锁对比? ? ? ? 在?Redis-分布式锁_小王师傅66的博客-CSDN博客?文章中,我们讲了Redis分布式锁。上面也分享了ZooKeeper分布式锁,我们知道了Redis主要是通过setnx命令实现分布式锁,Zookeeper采用临时节点和事件监听机制可以实现分布式锁。那么这两种方式有哪些关键的区别呢? 1、Redis分布式锁,获取不到锁时,需要不断轮询去尝试获取锁,比较消耗性能;ZooKeeper分布式锁,获取不到锁时,注册监听器即可,不需要不断主动尝试获取锁,性能开销较小; 2、锁未释放时服务器宕机。Redis只能等超时时间到将锁释放。ZooKeeper的临时节点检测不到服务器的心跳,节点移除,锁自动被释放; ? ? ? ? 这样看好像ZooKeeper比Redis更胜一筹,但Redis提供的API和库更加丰富,在很大程度上能够减少开发的工作量。而且如果是小规模的项目,已经部署了Redis,可能没太大必要去再部署一套ZooKeeper集群去实现分布式锁,大家根据场景自行选择。 总结? ? ? ? 在分布式环境中,使用分布式锁的场景非常多,ZooKeeper的监听机制和临时节点特性可以帮助我们实现强一致的分布式锁功能。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 17:14:10- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |