Zookeeper介绍以及使用

一、什么是 Zookeeper

高可用的发布/订阅模式的分布式数据管理和系统协调框架,基于ZAB算法的实现,该框架能够很好的保证分布式环境中数据的一致性

二、分布式一致性算法原理:Paxos 算法和 Zab 算法

1. Paxos 算法

推荐阅读博客:http://blog.jobbole.com/110389/

2. zookeeper 底层实现使用的算法:Paxos 算法的简化以及优化——Zab 算法

推荐阅读博客:http://www.cnblogs.com/sunddenly/articles/4073157.html

三、服务部署

  • 官方建议: 奇数机房部署总共奇数套程序组成集群,从而保证高可用性,因为zookeeper的是存活过半集群就仍可用
  • 前置条件: 安装JDK并配置好java_home
useradd zookeeper
chmod 775 -R /home/zookeeper
su - zookeeper
wget http://mirror.bit.edu.cn/apache/zookeeper/stable/zookeeper-3.4.10.tar.gz
1、部署步骤

1、单机模式

  • 将下载的 ZooKeeper 解压,进入 conf 目录,复制一份 zoo_sample.cfg 的配置文件命名为 zoo.cfg,修改如下:
tickTime=2000
dataDir=/home/zookeeper/data
clientPort=2181
  • 进入 bin 目录,启动 ZooKeeper:
./zkServer.sh start
  • 进入 bin 目录,使用客户端连接 Zookeeper
./zkCli.sh -server 127.0.0.1:2181
  • 出现客户端终端即为连接成功:
WATCHER::

WatchedEvent state:SyncConnected type:None path:null

[zk: 127.0.0.1:2181(CONNECTED) 0] 
  • 进入 bin 目录,关闭 ZooKeeper
zookeeper@localhost bin]$ ./zkServer.sh stop
ZooKeeper JMX enabled by default
Using config: /home/zookeeper/zookeeper-3.4.10/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED

2、伪集群

创建环境

[zookeeper@localhost ~]$ mkdir zookeeper01
[zookeeper@localhost ~]$ mkdir zookeeper02
[zookeeper@localhost ~]$ mkdir zookeeper03
[zookeeper@localhost ~]$ mkdir zookeeper01/data
[zookeeper@localhost ~]$ mkdir zookeeper02/data
[zookeeper@localhost ~]$ mkdir zookeeper03/data
[zookeeper@localhost ~]$ mkdir zookeeper01/conf
[zookeeper@localhost ~]$ mkdir zookeeper02/conf
[zookeeper@localhost ~]$ mkdir zookeeper03/conf
[zookeeper@localhost ~]$ touch zookeeper01/data/myid
[zookeeper@localhost ~]$ touch zookeeper02/data/myid
[zookeeper@localhost ~]$ touch zookeeper03/data/myid
[zookeeper@localhost ~]$ echo 1 > zookeeper01/data/myid 
[zookeeper@localhost ~]$ echo 2 > zookeeper02/data/myid 
[zookeeper@localhost ~]$ echo 3 > zookeeper03/data/myid 
[zookeeper@localhost ~]$ cp zookeeper-3.4.10/conf/zoo_sample.cfg zookeeper01/conf/zoo.cfg
[zookeeper@localhost ~]$ cp zookeeper-3.4.10/conf/zoo_sample.cfg zookeeper02/conf/zoo.cfg
[zookeeper@localhost ~]$ cp zookeeper-3.4.10/conf/zoo_sample.cfg zookeeper03/conf/zoo.cfg

修改zoo.cfg内容

[zookeeper@localhost ~]$ sed -i "s/\/tmp\/zookeeper/\/home\/zookeeper\/zookeeper01\/data/" zookeeper01/conf/zoo.cfg
[zookeeper@localhost ~]$ sed -i "s/\/tmp\/zookeeper/\/home\/zookeeper\/zookeeper02\/data/" zookeeper02/conf/zoo.cfg
[zookeeper@localhost ~]$ sed -i "s/\/tmp\/zookeeper/\/home\/zookeeper\/zookeeper03\/data/" zookeeper03/conf/zoo.cfg
[zookeeper@localhost ~]$ sed -i "s/2181/2182/" zookeeper02/conf/zoo.cfg
[zookeeper@localhost ~]$ sed -i "s/2181/2183/" zookeeper03/conf/zoo.cfg
[zookeeper@localhost ~]$ echo -e "server.1=127.0.0.1:3887:2887\nserver.2=localhost:3888:2888\nserver.3=127.0.0.1:3889:2889" >>  zookeeper01/conf/zoo.cfg
[zookeeper@localhost ~]$ echo -e "server.1=127.0.0.1:3887:2887\nserver.2=localhost:3888:2888\nserver.3=127.0.0.1:3889:2889" >>  zookeeper02/conf/zoo.cfg
[zookeeper@localhost ~]$ echo -e "server.1=127.0.0.1:3887:2887\nserver.2=localhost:3888:2888\nserver.3=127.0.0.1:3889:2889" >>  zookeeper03/conf/zoo.cfg
  • 启动集群
[zookeeper@localhost ~]$ sh zookeeper-3.4.10/bin/zkServer.sh start  zookeeper01/conf/zoo.cfg
ZooKeeper JMX enabled by default
Using config: zookeeper01/conf/zoo.cfg
Starting zookeeper ... STARTED
[zookeeper@localhost ~]$ sh zookeeper-3.4.10/bin/zkServer.sh start  zookeeper02/conf/zoo.cfg
ZooKeeper JMX enabled by default
Using config: zookeeper02/conf/zoo.cfg
Starting zookeeper ... STARTED
[zookeeper@localhost ~]$ sh zookeeper-3.4.10/bin/zkServer.sh start  zookeeper03/conf/zoo.cfg
ZooKeeper JMX enabled by default
Using config: zookeeper03/conf/zoo.cfg
Starting zookeeper ... STARTED

备份 startall.sh

[zookeeper@localhost ~]$ vi startall.sh 
sh zookeeper-3.4.10/bin/zkServer.sh start  zookeeper01/conf/zoo.cfg
sh zookeeper-3.4.10/bin/zkServer.sh start  zookeeper02/conf/zoo.cfg
sh zookeeper-3.4.10/bin/zkServer.sh start  zookeeper03/conf/zoo.cfg
[zookeeper@localhost ~]$ chmod +x startall.sh 
  • 停止集群
[zookeeper@localhost ~]$ sh zookeeper-3.4.10/bin/zkServer.sh stop  zookeeper01/conf/zoo.cfg
ZooKeeper JMX enabled by default
Using config: zookeeper01/conf/zoo.cfg
Stopping zookeeper ... STOPPED
[zookeeper@localhost ~]$ sh zookeeper-3.4.10/bin/zkServer.sh stop  zookeeper02/conf/zoo.cfg
ZooKeeper JMX enabled by default
Using config: zookeeper02/conf/zoo.cfg
Stopping zookeeper ... STOPPED
[zookeeper@localhost ~]$ sh zookeeper-3.4.10/bin/zkServer.sh stop  zookeeper03/conf/zoo.cfg
ZooKeeper JMX enabled by default
Using config: zookeeper03/conf/zoo.cfg
Stopping zookeeper ... STOPPED

备份 stopall.sh

[zookeeper@localhost ~]$ vi stopall.sh 
sh zookeeper-3.4.10/bin/zkServer.sh stop  zookeeper01/conf/zoo.cfg
sh zookeeper-3.4.10/bin/zkServer.sh stop  zookeeper02/conf/zoo.cfg
sh zookeeper-3.4.10/bin/zkServer.sh stop  zookeeper03/conf/zoo.cfg
[zookeeper@localhost ~]$ chmod +x stopall.sh 
  • 查看集群状态
[zookeeper@localhost ~]$ sh zookeeper-3.4.10/bin/zkServer.sh status  zookeeper01/conf/zoo.cfg
ZooKeeper JMX enabled by default
Using config: zookeeper01/conf/zoo.cfg
Mode: follower
[zookeeper@localhost ~]$ sh zookeeper-3.4.10/bin/zkServer.sh status  zookeeper02/conf/zoo.cfg
ZooKeeper JMX enabled by default
Using config: zookeeper02/conf/zoo.cfg
Mode: leader
[zookeeper@localhost ~]$ sh zookeeper-3.4.10/bin/zkServer.sh status  zookeeper03/conf/zoo.cfg
ZooKeeper JMX enabled by default
Using config: zookeeper03/conf/zoo.cfg
Mode: follower
  • 使用客户端验证
    连接其中一个节点操作,然后连接另一个节点,查看数据,如一直即为集群搭建成功
[zookeeper@localhost ~]$ sh zookeeper-3.4.10/bin/zkCli.sh -server 127.0.0.1:2181

# 创建测试节点

WATCHER::

WatchedEvent state:SyncConnected type:None path:null

[zk: 127.0.0.1:2181(CONNECTED) 0] create /testNode testData
Created /testNode
[zk: 127.0.0.1:2181(CONNECTED) 1] ls /
[zookeeper, testNode]


[zookeeper@localhost ~]$ sh zookeeper-3.4.10/bin/zkCli.sh -server 127.0.0.1:2182

WATCHER::

WatchedEvent state:SyncConnected type:None path:null
[zk: 127.0.0.1:2182(CONNECTED) 0] ls /
[zookeeper, testNode]
3、多主机集群模式 - 单机模式一样的配置zoo.cfg - 在对应的dataDir目录下配置添加myid文件 - 在zoo.cfg 后面追加对应的 server.A=B:C:D 列表,这个和伪集群模式类似 - 启动和停止方式与单机模式一致 - 验证参考伪集群模式 4、配置说明
  • tickTime:发送心跳的间隔时间,单位:毫秒
  • dataDir:zookeeper保存数据的目录。
  • clientPort:客户端连接 Zookeeper 服务器的端口,Zookeeper 会监听这个端口,接受客户端的访问请求。
  • initLimit:这个配置项是用来配置 Zookeeper 接受客户端(这里所说的客户端不是用户连接 Zookeeper 服务器的客户端,而是 Zookeeper 服务器集群中连接到 Leader 的 Follower 服务器)初始化连接时最长能忍受多少个心跳时间间隔数。当已经超过 5个心跳的时间(也就是 tickTime)长度后 Zookeeper 服务器还没有收到客户端的返回信息,那么表明这个客户端连接失败。总的时间长度就是 5*2000=10 秒
  • syncLimit:这个配置项标识 Leader 与 Follower 之间发送消息,请求和应答时间长度,最长不能超过多少个 tickTime 的时间长度,总的时间长度就是 2*2000=4 秒
  • server.A=B:C:D : 其中 A 是一个数字对应相应data目录下的myid的内容,表示这个是第几号服务器;B 是这个服务器的 ip 地址;C 表示的是这个服务器与集群中的 Leader 服务器交换信息的端口;D 表示的是万一集群中的 Leader 服务器挂了,需要一个端口来重新进行选举,选出一个新的 Leader,而这个端口就是用来执行选举时服务器相互通信的端口。如果是伪集群的配置方式,由于 B 都是一样,所以不同的 Zookeeper 实例通信端口号不能一样,所以要给它们分配不同的端口号。
2、zkCli客户端操作原语集
  • help 帮助指令,列出可操作的相关指令
ZooKeeper -server host:port cmd args
    stat path [watch]
    set path data [version]
    ls path [watch]
    delquota [-n|-b] path
    ls2 path [watch]
    setAcl path acl
    setquota -n|-b val path
    history 
    redo cmdno
    printwatches on|off
    delete path [version]
    sync path
    listquota path
    rmr path
    get path [watch]
    create [-s] [-e] path data acl
    addauth scheme auth
    quit 
    getAcl path
    close 
    connect host:port
  • create /test_znode test_data :创建节点/test_znode 并 数据节点test_data
[zk: 127.0.0.1:2181(CONNECTED) 1] create /test_znode test_data
Created /test_znode
  • ls /:列出 / 下的节点信息
[zk: 127.0.0.1:2181(CONNECTED) 2] ls /
[zookeeper, test_znode]
  • get /test_znode :获取/test_znode 节点信息
[zk: 127.0.0.1:2181(CONNECTED) 0] get /test_znode
test_data
cZxid = 0x4
ctime = Wed Mar 28 07:28:54 PDT 2018
mZxid = 0x4
mtime = Wed Mar 28 07:28:54 PDT 2018
pZxid = 0x4
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 9
numChildren = 0
  • set /test_znode other_data :更新 /test_znode节点的数据信息
[zk: 127.0.0.1:2181(CONNECTED) 0] set /test_znode other_data
cZxid = 0x4
ctime = Wed Mar 28 07:28:54 PDT 2018
mZxid = 0x9
mtime = Wed Mar 28 07:41:05 PDT 2018
pZxid = 0x4
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 10
numChildren = 0
  • delete /test_znode : 删除 /test_znode 这个节点
[zk: 127.0.0.1:2181(CONNECTED) 0] delete /test_znode
[zk: 127.0.0.1:2181(CONNECTED) 1] ls /
[zookeeper]
  • watch :监听节点的更新和数据的更新
    操作节点
[zk: 127.0.0.1:2181(CONNECTED) 2] ls /testNode          
[]
[zk: 127.0.0.1:2181(CONNECTED) 3]  rmr /testNode 

监听节点更新


[zk: 127.0.0.1:2182(CONNECTED) 0] ls /testNode
[]
[zk: 127.0.0.1:2182(CONNECTED) 1] ls /testNode watch

WATCHER::

WatchedEvent state:SyncConnected type:NodeDeleted path:/testNode

操作节点的数据

[zk: 127.0.0.1:2181(CONNECTED) 0] set /nodetest test2
cZxid = 0x300000011
ctime = Wed Mar 28 10:39:51 PDT 2018
mZxid = 0x300000013
mtime = Wed Mar 28 10:42:31 PDT 2018
pZxid = 0x300000011
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
[zk: 127.0.0.1:2181(CONNECTED) 1] 

监控数据更新

[zk: 127.0.0.1:2182(CONNECTED) 1] get /nodetest watch
test1
cZxid = 0x300000011
ctime = Wed Mar 28 10:39:51 PDT 2018
mZxid = 0x300000011
mtime = Wed Mar 28 10:39:51 PDT 2018
pZxid = 0x300000011
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
[zk: 127.0.0.1:2182(CONNECTED) 2]           
WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/nodetest

四、Zookeeper内部存储数据的数据模型:ZNode的数据结构以及特性

推荐阅读博客:https://segmentfault.com/a/1190000005641108

1. 保存在内存中的类似linux文件系统的树
  • 存储于内存中实现高吞吐量和低延迟数量的保证

  • 最上层有一个根节点 /,根节点下有子节点,字节点下又能递归地拥有子节点。
    没有任何子节点的节点称之为叶子节点。
    在zookeeper的术语中,节点称之为Znode。

  • 每个节点的数据信息的大小其实很少

2. 特性:持久性和会话性

一个znode会有两种可能的mode,持久性和挥发性各有各的应用场景:
- 持久性的znode会一直存在,因此持久性的znode适合用来存储一些全局性,共享性的数据。比如说,配置信息,任务信息。
- 会话性的znode在客户端的session结束后或者是zookeeper服务器停止运行的时候会被删除。挥发性的znode适合用来存储与会话相关的数据,比如说一个客户端的状态,一个客户端持有的锁,与会话相关的数据,应随着会话的生死而生死。

3. 提供对ZNode的多种操作的监听接口

推荐阅读博客:https://blog.youkuaiyun.com/qianshangding0708/article/details/50084155

  • ZooKeeper中Watch事件(见:org.apache.zookeeper.Watcher.EventType):
事件描述
None在客户端与Zookeeper集群中的服务器断开连接的时候,客户端会收到这个事件。
NodeCreatedZnode创建事件
NodeDeletedZnode删除事件
NodeDataChangedZnode数据内容更新事件。其实本质上该事件只关注dataVersion版本号,但是只要调用了更新接口dataVersion就会有变更。
NodeChildrenChangedZnode子节点改变事件,只关注子节点的个数变更,子节点内容有变更是不会通知的。

- 在事件发生时,ZooKeeper的状态(见:org.apache.zookeeper.Watcher.KeeperState:

事件描述
Disconnected(0)客户端处于断开连接的状态,并且没有和Zookeeper集群中任何服务器连接。
SyncConnected(3)客户端处于连接的状态,也就是说客户端连接到了一台server
AuthFailed(4)验证失败的状态
ConnectedReadOnly(5)客户端连接到一个只读Server的状态。
SaslAuthenticated(6)用于通知客户端他们是SASL认证,以至于他们能够SASL认证的权限通过操作Zookeeper。
Expired(-112)会话超时状态

五、 Zookeeper 的 Jave 客户端的介绍和使用

  • 推荐单独开发工具使用:Curator
1、Zookeeper原生API

推荐阅读博客:http://www.cnblogs.com/shengkejava/p/5611671.html

2、Curator

推荐阅读博客:https://www.jianshu.com/p/70151fc0ef5d

3、ZkClient

推荐阅读博客:https://blog.youkuaiyun.com/wo541075754/article/details/68929512

六、常见应用场景以及具体实现

1. 数据的发布订阅
基于高效缓存的数据结构,以及ZNode监听实现数据的发布订阅,所有的功能几乎都是基于此实现的
  • 发布/订阅模式是一对多的关系,多个订阅者对象同时监听某一主题对象,这个主题对象在自身状态发生变化时会通知所有的订阅者对象。使它们能自动的更新自己的状态。发布/订阅可以使得发布方和订阅方独立封装、独立改变。当一个对象的改变需要同时改变其他对象,而且它不知道具体有多少对象需要改变时可以使用发布/订阅模式。发布/订阅模式在分布式系统中的典型应用有配置管理和服务发现、注册。

  • 配置管理是指如果集群中的机器拥有某些相同的配置并且这些配置信息需要动态的改变,我们可以使用发布/订阅模式把配置做统一集中管理,让这些机器格子各自订阅配置信息的改变,当配置发生改变时,这些机器就可以得到通知并更新为最新的配置。

  • 服务发现、注册是指对集群中的服务上下线做统一管理。每个工作服务器都可以作为数据的发布方向集群注册自己的基本信息,而让某些监控服务器作为订阅方,订阅工作服务器的基本信息,当工作服务器的基本信息发生改变如上下线、服务器角色或服务范围变更,监控服务器可以得到通知并响应这些变化。

dubbo中使用zookeeper作为注册中心,注册维护服务提供者和消费者的相关信息

推荐阅读源码:com.alibaba.dubbo.registry下com.alibaba.dubbo.registry.zookeeper的相关实现
推荐阅读博客:https://blog.youkuaiyun.com/joeyon1985/article/details/51046603

2. 负载均衡
zookeeper 临时节点的会话性,服务在某个节点下注册对应的临时节点,监听者监听该节点下子节点的更新,确保知道能正常提供服务的节点,会话就会继续保持。临时节点会继续存在,再由监听者根据现有的健康节点,实现请求转发的负载均衡,无法保持会话的服务节点,临时节点将会剔除,从而触发监控服务节点的消费者将之从服务提供列表中提出,重新指定负载均衡策略
消息队列 kafka 的生产者和消费者的负载均衡即是基于 Zookeeper 开发的,有兴趣可以了解一下, Consumer 消费的 Partition 的负载均衡策略,Partition 和 Consumer 的关系是多对一, Consumer 在 zookeeper 中注册消费信息,当有 Consumer 加入或者退出时, Kafka 的服务端会听到数据变化,从而重新分配 Partition 内的数据由哪个 Consumer 接收 ,Producer 往哪个 Partition推送数据的负载均衡策略是可以用户定制的,具体用户自己实现 kafka client 端的org.apache.kafka.clients.producer.Partitioner 接口,Partition会有默认的初始数量,而且不会自动扩容,所以如果按照默认初始的数量使用的话,根据一对多的关系,Consumer 的数量超过 Partition 将会有部分消费者不起作用,消息较多的情况下创建 Topic 的同时推荐先新建分配更多 Partition 和 Consumer 防止消息堆积过多把 kafka 爆炸了

3. 命名服务
命名服务是指通过指定的名字来获取资源或者服务的地址,提供者的信息。利用Zookeeper很容易创建一个全局的路径,而这个路径就可以作为一个名字,它可以指向集群中的集群,提供的服务的地址,远程对象等。简单来说使用Zookeeper做命名服务就是用路径作为名字,路径上的数据就是其名字指向的实体。
最经典的例子即时dubbo使用ZooKeeper来作为其命名服务,维护全局的服务地址列表。在Dubbo实现中服务提供者在启动的时候,向ZK上的指定节点/dubbo/${serviceName}/providers目录下写入自己的URL地址,这个操作就完成了服务的发布。
  • 服务消费者启动的时候,订阅/dubbo/{serviceName}/providers目录下的提供者URL地址, 并向/dubbo/{serviceName} /consumers目录下写入自己的URL地址。
  • 注意,所有向ZK上注册的地址都是临时节点,这样就能够保证服务提供者和消费者能够自动感应资源的变化。
  • 另外,Dubbo还有针对服务粒度的监控,方法是订阅/dubbo/{serviceName}目录下所有提供者和消费者的信息。
4. 分布式协调通知
Zookeeper中特有的Watcher注册与异步通知机制,能够很好的实现分布式环境下不同机器,甚至是不同系统之间的协调与通知,从而实现对数据变更的实时处理。基于Zookeeper实现分布式协调与通知功能,从而实现对数据变更的实时处理。基于ZooKeeper实现分布式协调与通知功能,通常的做法是不同的客户端都对Zookeeper上同一个数据节点进行Watcher注册,监听数据节点的变化(包括数据节点本身及其子节点),如果数据节点发生变化,那么所有订阅的客户端都能够接收到相应的Watcher通知,并做出相应的处理。
MySQL数据复制总线:Mysql_Replicator
5. 集群管理

集群管理,包括集群监控与集群控制两大块,前者侧重对集群运行时状态的收集,后者则是对集群进行操作与控制。在日常开发和运维过程中,我们经常会有类似于如下的需求。
- 希望知道当前集群中究竟有多少机器在工作。
- 对集群中每台机器的运行时状态进行数据收集。
- 对集群中机器进行上下线操作。

ZooKeeper具有以下两大特性。
  • 客户端如果对ZooKeeper的一个数据节点注册Watcher监听,那么当该数据节点的内容或是其子节点列表发生变更时,ZooKeeper服务器就会向订阅的客户端发送变更通知。
  • 对在ZooKeeper上创建的临时节点,一旦客户端与服务器之间的会话失效,那么该临时节点也就被自动清除。

利用ZooKeeper的这两大特性,就可以实现另一种集群机器存活性监控的系统。例如,监控系统在/clusterServers节点上注册一个Watcher监听,那么但凡进行动态添加机器的操作,就会在/clusterServers节点下创建一个临时节点/clusterServer/[Hostname]。这样一来,监控系统就能够实时检测到机器的变动情况,至于后续处理就是监控系统的业务了。下面我们就通过分布式日志收集系统和在线云主机管理这两个典型例子来看看如何使用ZooKeeper实现集群管理。

dubbo管理控制台以zookeeper作为注册中心时,dubbo-monitor底层即用了这个思想完成实现服务集群的监控和管理的
6. Master 选举
在分布式系统中,Master往往用来协调集群中其他系统单元,具有对分布式系统状态变更的决定权。例如,在一些读写分离的应用场景中,客户端的写请求往往是由Master来处理的;而在另一些场景中,Master则常常负责处理一些复杂的逻辑,并将处理结果同步给集群中其他系统单元。Master选举可以说是ZooKeeper最典型的应用场景了
利用ZooKeeper的强一致性,能够很好的保证在分布式高并发情况下节点的创建一定能够保证全局唯一性,即ZooKeeper将会保证客户端无法重复创建一个已经存在的数据节点。也就是说,如果同时有多个客户端请求创建同一个节点,那么最终一定只有一个客户端请求能够创建成功。利用这个特性,就能很容易的分布式环境中进行Master选举了。
Master选举时极端情况下的反例:Redis集群中进行 Master 选举时 Redis Sentinel的脑裂现象

Redis Cluster is not able to guarantee strong consistency. / In general Redis + Sentinel as a whole are a an eventually consistent system

推荐阅读博客:http://www.cnblogs.com/yjmyzz/p/redis-split-brain-analysis.html
7. 分布式锁
  • 1、独占锁
    1. 多个客户端竞争创建 lock 临时节点
    2. 其中某个客户端成功创建 lock 节点,其他客户端对 lock 节点设置 watcher
    3. 持有锁的客户端删除 lock 节点或该客户端崩溃,由 Zookeeper 删除 lock 节点
    4. 其他客户端获得 lock 节点被删除的通知
    5. 重复上述4个步骤,直至无客户端在等待获取锁了

  • 2、读写锁
    1. 所有客户端创建自己的锁节点
    2. 从 Zookeeper 端获取 /share_lock 下所有的子节点
    3. 判断自己创建的锁节点是否可以获取锁,如果可以,持有锁。否则对自己关心的锁节点设置 watcher
    4. 持有锁的客户端删除自己的锁节点,某个客户端收到该节点被删除的通知,并获取锁
    5. 重复步骤4,直至无客户端在等待获取锁了

推荐阅读博客:https://segmentfault.com/a/1190000010895869

推荐阅读博客:https://www.jianshu.com/p/5d12a01018e1

8. 分布式队列
从现实考虑时不推荐zookeeper作为分布式存储单元的,推荐如果要使用分布式队列的话,使用 Redis 现成的队列实现,队列相应的方法实现都有现成的命令实现可以调用,

https://blog.youkuaiyun.com/zuoanyinxiang/article/details/50946328

9. 分布式 barrier
Barrier愿意是指障碍物、屏障,而在分布式系统中,特指系统之间的一个协调条件,规定了一个队列的元素必须都集聚后才能统一进行安排,否则一直等待。这往往出现在那些大规模分布式并行计算的应用场景上:最终的合并计算需要基于很多并行计算的子结果来进行。

推荐阅读博客:https://blog.youkuaiyun.com/en_joker/article/details/78809236

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值