当前位置: 首页 > article >正文

zookeeper-docker版

Zookeeper-docker版

1 zookeeper概述

1.1 什么是zookeeper

Zookeeper是一个分布式的、高性能的、开源的分布式系统的协调(Coordination)服务,它是一个为分布式应用提供一致性服务的软件。

1.2 zookeeper应用场景

zookeeper是一个经典的分布式数据一致性解决方案,致力于为分布式应用提供一个高性能,高可用,且具有严格属性访问控制能力的分布式协调存储服务。

1、维护配置信息

java编程经常会遇到配置项,比如数据库的url,schema,user和password等。通常这些配置项我们会放置在配置文件中,在将配置文件放置在服务器上当需要更改配置的时,需要去服务器上修改对应的配置信息文件。但是随着分布式系统的兴起,由于许多服务都需要使用到该配置文件,必须保证该配置服务的高可用性和各台服务器上配置数据的一致性。因此,通常会将配置文件部署在一个集群上,然而一个集群动辄上前台服务器,此时如果在一台一台服务器逐个的修改配置文件将是非常繁琐的一个操作。因此就需要一种服务,能够高效快速且可靠的完成配置项的更新等操作,并能够保证各个配置项在每一台服务器上的数据一致性。

zookeeper就可以提供这样一种服务,其使用Zab这种一致性协议来保证一致性。现在有很多开源项目使用zookeeper来维护配置,比如hhase中,客户端就是连接一个zookeeper,获得必要hbase集群的配置信息然后才可以进一步操作。还有开源的消息队列kafka中,也是用zookeeper来维护broker的信息。

2、分布式锁服务

一个集群是一个分布式系统,有多台服务器组成。为了提高并发度和可靠性,多台服务器运行着同一种服务。当多个服务在运行时就需要协调各服务的进度,有时候需要保证当某个服务在进行某个操作时,其他的服务都不能进行该操作,即对该操作进行加锁,如果当前机器挂掉后,并释放fail over到其他的机器继续执行该服务。

3、集群管理

一个集群优势会因为各种软硬件故障或者网络故障,出现某种服务器挂掉而被移除集群,而某些服务器加入到集群中的情况,zookeeper会将这些服务器加入/移出的情况下通知给集群汇总的其他正常工作的服务器,以及时调用存储和计算等任务的分配和执行等。此外zookeeper还会对故障的服务器做出诊断并尝试修复。

4、生成分布式唯一ID

在过去的单库单表型系统中,通常可以使用数据库字段自带的auto_increment属性来自动为每条记录生成一个唯一的ID。但是分库分表后,就无法再依靠数据库的auto_increatment属性来唯一标识一条记录了,此时我们就可以用zookeeper在分布式环境下生成全局唯一ID。做法如下:每一个生成一个新ID时,创建一个持久顺序节点,创建操作返回的节点序号,然后把比自己节点小的删除即可。

1.3 zookeeper的设计目标

zookeeper致力于为分布式应用提供一个高性能,高可用,具有严格顺序访问控制能力的分布式协调服务。

1、高性能

zookeeper将全量数据存储在内存中,并直接服务与客户端的所有非事务请求,尤其适合用于以读为主的应用场景。

2、高可用

zookeeper一般以集群的范式对外提供服务,一般3-5台机器就可以组成一个可用的zookeeper集群,每一台机器都会在内存中维护当前的服务器状态,并且每台机器之间都相互保持着通信。只要集群中超过一台的机器都在工作,那么这个集群就能够正常对外服务;

3、严格访问数据

对于客户端的每一个更新请求,Zookeeper都会分配一个全局唯一的递增编号,这个编号反映了所有事务操作的先后顺序。

2 Zookeeper的数据模型

2.1 zookeeper数据结构

Zookeeper数据模型的结构与Unix文件系统很类似,整体上可以看作是一颗树,每一个节点称做一个ZNode。每一个Znode默认能够存储1MB的数据,每个ZNode都可以通过其路径唯一标识。

如何来描述一个ZNode呢?一个znode大体上分为3部分:

(1)节点的数据:即znode data(节点path,节点data的关系)就像是java map中(key,value)的关系。

(2)节点的子节点children

(2)节点的状态stat:用来描述当前节点的创建,修改记录,包括czxid、ctime等。

2.2 zookeeper节点类型

zookeeper中的节点有两种类型,一种是临时节点和永久节点。节点类型在创建是即被确定,并且不能改变。

(1)临时节点:该节点的生命周期依赖于创建他们的会话。一旦会话(Session)结束,临时节点将会被自动删除,当然可以手动的进行删除。虽然每个临时的ZNode都会绑定到一个客户端会话,但他们对所有的客户端还是可见的。另外,Zookeeper的临时节点不允许拥有子节点。

(2)持久化节点:该节点的生命周期不依赖于会话,并且只有在客户点显示执行删除操作的时候,他们才能被删除。

3 docker部署Zookeeper

3.1 部署准备

1、下载镜像

[root@hadoop104 ~]# docker pull zookeeper:3.5.8

2、创建局域网

在集群部署在同一个局域网中。

[root@hadoop104 ~]# docker network create --subnet=192.168.10.0/24 zk_net

3、创建节点挂载目录

(1)集群规划,集群部署3台机器:

集群编号ZOO_MY_ID名称映射本地端口ip存储路径
1zk12181192.168.10.101/usr/local zookeeper/zk1
2zk22182192.168.10.102/usr/local zookeeper/zk2
3zk32183192.168.10.103/usr/local zookeeper/zk3

(2)创建节点挂载目录

[root@hadoop104 ~]# cd /usr/local

#创建 zookeeper节点配置存放目录

[root@hadoop104 local]# mkdir -p zookeeper/zk1/conf zookeeper/zk2/conf zookeeper/zk3/conf

#创建 zookeeper节点数据存放目录

[root@hadoop104 local]# mkdir -p zookeeper/zk1/data zookeeper/zk2/data zookeeper/zk3/data

#创建 zookeeper节点数据日志存放目录

[root@hadoop104 local]# mkdir -p zookeeper/zk1/datalog zookeeper/zk2/datalog zookeeper/zk3/datalog

#创建 zookeeper节点日志存放目录

[root@hadoop104 local]# mkdir -p zookeeper/zk1/logs zookeeper/zk2/logs zookeeper/zk3/logs

4、创建配置文件

(1)在第1个节点挂载目录zookeeper/zk1/conf下分别创建配置文件zoo.cfg

[root@hadoop104 local]# vim zookeeper/zk1/conf/zoo.cfg

内容如下:

#Zookeeper保存数据的目录,默认情况下,Zookeeper将写数据的日志文件也保存在这个目录里

dataDir=/data

#事务日志存储地点,如果没提供的话使用的则是 dataDir

dataLogDir=/datalog

#服务器之间或客户端与服务器之间维持心跳的时间间隔,也就是每个 tickTime 时间就会发送一个心跳。tickTime以毫秒为单位

tickTime=2000

#集群中的follower服务器(F)与leader服务器(L)之间初始连接时能容忍的最多心跳数(tickTime的数量)

initLimit=5

#集群中的follower服务器与leader服务器之间请求和应答之间能容忍的最多心跳数(tickTime的数量)

syncLimit=2

#默认值为3,不支持以系统属性方式配置。用于配置Zookeeper在自动清理的时候需要保留的快照数据文件数量和对应的事务日志文件。此参数的最小值为3,如果配置的值小于3会自动调整到3

autopurge.snapRetainCount=3

#默认值为0,单位为小时,不支持以系统属性方式配置。用于配置Zookeeper进行历史文件自动清理的频率。如果配置为0或负数,表示不需要开启定时清理功能

autopurge.purgeInterval=0

#默认为60,不支持以系统属性方式配置。从Socket层面限制单个客户端与单台服务器之间的并发连接数,即以ip地址来进行连接数的限制。

#如果设置为0,表示不做任何限制。仅仅是单台客户端与单个Zookeeper服务器连接数的限制,不能控制所有客户端的连接数总和

maxClientCnxns=60

#3.5.0中的新功能:当设置为false时,可以在复制模式下启动单个服务器,单个参与者可以使用观察者运行,并且群集可以重新配置为一个节点,并且从一个节点。

#对于向后兼容性,默认值为true。可以使用QuorumPeerConfig的setStandaloneEnabled方法或通过将“standaloneEnabled = false”或“standaloneEnabled = true”添加到服务器的配置文件来设置它。

standaloneEnabled=false

#内嵌的管理控制台,停用这个服务

admin.enableServer=false

#开启四字命令,将所有命令添加到白名单中

4lw.commands.whitelist=*

#集群中服务的列表,ip设置为局域网zk_net的网段

server.1=192.168.10.101:2888:3888;2181

server.2=192.168.10.102:2888:3888;2181

server.3=192.168.10.103:2888:3888;2181

zoo.cfg配置文件中参数的说明 解释说明:

tickTime=2000zookeeper里面最小的时间单位为2000ms
initLimit=10Follower在启动过程中,会从Leader同步所有最新数据,然后确定自己能够对外服务的起始状态。Leader允许F在 initLimit 时间内完成这个工作。通常情况下,我们不用太在意这个参数的设置。如果ZK集群的数据量确实很大了,F在启动的时候,从Leader上同步数据的时间也会相应变长,因此在这种情况下,有必要适当调大这个参数了
syncLimit=5在运行过程中,Leader负责与ZK集群中所有机器进行通信,例如通过一些心跳检测机制,来检测机器的存活状态。如果L发出心跳包在syncLimit之后,还没有从F那里收到响应,那么就认为这个F已经不在线了。注意:不要把这个参数设置得过大,否则可能会掩盖一些问题
dataDir存储快照文件snapshot的目录。默认情况下,事务日志也会存储在这里。建议同时配置参数dataLogDir, 事务日志的写性能直接影响zk性能
dataLogDir事务日志输出目录。尽量给事务日志的输出配置单独的磁盘或是挂载点,这将极大的提升ZK性能
clientPort客户端连接server的端口,即对外服务端口 ,默认是2181
server.1配置集群节点
192.168.10.100:2888:3888主机名, 心跳端口、数据端口 的格式

(2)分别创建第2,3个节点的配置文件

[root@hadoop104 local]# cp zookeeper/zk1/conf/zoo.cfg zookeeper/zk2/conf

[root@hadoop104 local]# cp zookeeper/zk1/conf/zoo.cfg zookeeper/zk3/conf

3.2 部署节点

(1)安装并启动第1个节点

[root@hadoop104 ~]# docker run -d --restart always --name zk1 --network zk_net --ip 192.168.10.101 -p 2181:2181 -e ZOO_MY_ID=1 -v /usr/local/zookeeper/zk1/data:/data -v /usr/local/zookeeper/zk1/datalog:/datalog -v /usr/local/zookeeper/zk1/logs:/logs -v /usr/local/zookeeper/zk1/conf/zoo.cfg:/conf/zoo.cfg zookeeper:3.5.8

(2)安装并启动第2个节点

[root@hadoop104 ~]# docker run -d --restart always --name zk2 --network zk_net --ip 192.168.10.102 -p 2182:2181 -e ZOO_MY_ID=2 -v /usr/local/zookeeper/zk2/data:/data -v /usr/local/zookeeper/zk2/datalog:/datalog -v /usr/local/zookeeper/zk2/logs:/logs -v /usr/local/zookeeper/zk2/conf/zoo.cfg:/conf/zoo.cfg zookeeper:3.5.8

(3)安装并启动第3个节点

[root@hadoop104 ~]# docker run -d --restart always --name zk3 --network zk_net --ip 192.168.10.103 -p 2183:2181 -e ZOO_MY_ID=3 -v /usr/local/zookeeper/zk3/data:/data -v /usr/local/zookeeper/zk3/datalog:/datalog -v /usr/local/zookeeper/zk3/logs:/logs -v /usr/local/zookeeper/zk3/conf/zoo.cfg:/conf/zoo.cfg zookeeper:3.5.8

(4)查看节点状态

集群中3个节点,只有一个是leader,其它节点都为flower。

#第1个节点状态

[root@hadoop104 ~]# docker exec -it zk1 /bin/bash

root@245b7b533b30:/apache-zookeeper-3.5.8-bin# zkServer.sh status

ZooKeeper JMX enabled by default

Using config: /conf/zoo.cfg

Client port found: 2181. Client address: localhost.

Mode: follower

#第2个节点状态

[root@hadoop104 ~]# docker exec -it zk2 /bin/bash

root@36d3223cc495:/apache-zookeeper-3.5.8-bin# zkServer.sh status

ZooKeeper JMX enabled by default

Using config: /conf/zoo.cfg

Client port found: 2181. Client address: localhost.

Mode: leader

#第2个节点状态

[root@hadoop104 ~]# docker exec -it zk3 /bin/bash

root@450e6cf10d4f:/apache-zookeeper-3.5.8-bin# zkServer.sh status

ZooKeeper JMX enabled by default

Using config: /conf/zoo.cfg

Client port found: 2181. Client address: localhost.

Mode: follower

3个节点状态正常,集群搭建完成。

4 Zookeeper常用的Shell命令

4.1 基本操作

(1)连接ZooKeeper服务端:zkCli.sh –server ip:port

[root@hadoop104 ~]# docker exec -it zk1 /bin/bash

root@245b7b533b30:/apache-zookeeper-3.5.8-bin# zkCli.sh

[zk: localhost:2181(CONNECTED) 0]

(2)断开连接:quit

(3)查看命令帮助:help

(4)显示指定目录下节点:ls 目录

[zk: localhost:2181(CONNECTED) 7] ls /

[zookeeper]

4.2 新增节点

create [-s] [-e] path data # 其中 -s 为有序节点, -e 临时节点

(1)创建持久化节点并写入数据:

[zk: localhost:2181(CONNECTED) 0] create /test “123456”

Created /test

(2)创建持久化有序节,此时创建的节点名为指定节点名+自增序号

[zk: localhost:2181(CONNECTED) 2] create -s /test/sn “a”

Created /test/sn0000000001

[zk: localhost:2181(CONNECTED) 3] create -s /test/sn “b”

Created /test/sn0000000002

(3)创建临时节点,临时节点会在会话过期后被删除

[zk: localhost:2181(CONNECTED) 4] create -e /tmp “tmp”

Created /tmp

(4)创建临时有序节点,临时节点会在会话过期后被删除

[zk: localhost:2181(CONNECTED) 11] create -s -e /tmpsn “a”

Created /tmpsn0000000002

[zk: localhost:2181(CONNECTED) 12] create -s -e /tmpsn “b”

Created /tmpsn0000000003

4.3 获取节点数据

get -s path 或 stat path

(1)获取节点数据

[zk: localhost:2181(CONNECTED) 13] get /test

123456

(2)获取子节点数据

[zk: localhost:2181(CONNECTED) 15] get /test/sn0000000001

a

(3)查看详细信息

[zk: localhost:2181(CONNECTED) 20] get -s /test

123456

cZxid = 0x100000001

ctime = Thu Sep 12 07:33:53 UTC 2024

mZxid = 0x10000000b

mtime = Thu Sep 12 07:47:49 UTC 2024

pZxid = 0x100000005

cversion = 0

dataVersion = 0

aclVersion = 0

ephemeralOwner = 0x0

dataLength = 4

numChildren = 2

节点各个属性如下表。一个重要的概念是Zxid(ZooKeeper Transaction Id),ZooKeeper节点的每一个更改都具唯一的Zxid,如果Zxid1小于Zxid2,则Zxid1的更改发生在Zxid2更改之前。

状态属性节点说明
cZxid数据节点创建时的事务ID
ctime数据节点创建世的时间
mZxid数据节点最后一个更新是的事务ID
mtime数据节点最后一个跟新时的时间
pZxid数据节点的子节点最后一个被修改时的事务ID
cversion子节点的更改次数
dataVerion节点数据的更改次数
aclVersion节点ACL的更改次数
ephemeralOwner如果节点是临时节点,则表示创建该节点的会话的SeeesionID;如果是持久节点,则该属性值为0
dataLength数据内容的长度
numChildren数据节点当前的子节点个数

4.4 更新节点

set path data [version]

(1)使用set命令来更新节点

[zk: localhost:2181(CONNECTED) 16] set /test “7890”

[zk: localhost:2181(CONNECTED) 17] get /test

7890

(2)根据版本号来更新节点

[zk: localhost:2181(CONNECTED) 23] get -s /test

abcd

cZxid = 0x100000002

ctime = Thu Sep 12 07:33:53 UTC 2024

mZxid = 0x10000000c

mtime = Thu Sep 12 07:54:30 UTC 2024

pZxid = 0x100000005

cversion = 3

dataVersion = 2

aclVersion = 0

ephemeralOwner = 0x0

dataLength = 4

numChildren = 3

[zk: localhost:2181(CONNECTED) 24] set /test “abcd” 3

[zk: localhost:2181(CONNECTED) 25] get /test

abcd

也可以基于版本号来进行更改,此时类似于乐观锁机制,当你传入的数据版本号(dataVersion)和当前节点的数据版本号不符合时,zookeeper会拒绝本次修改:

4.5 删除节点

delete path [version]

和更新节点数据一样,也可以传入版本号,当你传入的数据版本号(dataVersion)和当前节点的数据版本号不符合时,zookeeper不会执行删除操作。

(1)删除节点

[zk: localhost:2181(CONNECTED) 27] delete /tmp

(2)要想删除某个节点及其所有后代节点,可以使用递归删除,命令为 rmr path 或 eleteall path。

[zk: localhost:2181(CONNECTED) 30] deleteall /test

4.6 监听器

get -w path或 stat -w path

使用get path [watch] 注册的监听器能够在节点内容发生改变的时候,向客户点发出通知。需要注意的是zookeeper的触发器是一次性的(One-time trigger),触发一次后就会立即失效。

使用stat path [watch] 注册的监听器能够在节点抓哪个台发生改变的时候,向客户点发出通知。

(1)监听节点变化

客户端窗口1

[zk: localhost:2181(CONNECTED) 32] create /watch “123456”

[zk: localhost:2181(CONNECTED) 35] stat -w /watch

另开一个客户端窗口2

[root@hadoop104 ~]# docker exec -it zk2 /bin/bash

root@36d3223cc495:/apache-zookeeper-3.5.8-bin# zkCli

[zk: localhost:2181(CONNECTED) 0] set /watch “abcd”

在客户端窗口1,输出以下结果:

WATCHER::

WatchedEvent state:SyncConnected type:NodeDataChanged path:/watch

5 zookeeper事件监听机制

5.1 watcher概念

zookeeper提供了数据的发布/订阅功能,对个订阅者可同时监听某一特定主题对象,当该主题对象的自身状态发生变化时(例如节点内容改变,节点下的子节点列表改变等),会实时,主动通知所有订阅者;

zookeeper采用了watcher机制实现数据的发布/订阅功能。该机制在被订阅对象发生变化时会异步通知客户端,因此客户端不必在Watcher注册后轮询阻塞,从而减轻了客户点压力。

watcher机制实际上与观察者密室类似,也可以看作是一种观察者密室在分布式场景下的实现方式。

5.2 wathcer架构

Watcher实现由三个部分组成:

  • Zookeeper服务端
  • Zookeeper客户端
  • 客户端的ZKWatchManager对象

客户端首先将Watcher注册到服务端,同时将Watcher对象保存到客户端的Watch管理器中。当Zookeeper服务端监听的数据状态发生变化时,服务端会主动通知客户端,接着客户端的Watch管理器会触发相关Watcher来回调相应处理逻辑,从而完成整体的数据发布/订阅流程。

5.3 wahcher特性

(1)一次性:wathcer是一次性的,一旦被触发就会移除,再次使用时需要重新注册。

(2)客户端顺序回调:watcher回调是顺序串行化执行的,只有回调后客户端才能看到最新的数据状态。一个watcher回调逻辑不用太多,以免影响别的watcher执行。

(3)轻量级:wathcerEvent是最小的通信单元,结构上只包含通知状态,事件类型和节点路径,并不会告诉数据节点变化前后的具体内容。

(4)时效性:watcher只有在当前session彻底失效时才会无效,若session有效期内快速重连成功。则wacher依然存在,然后可接收到通知。

6 zookeeper应用场景

6.1 配置中心案例

工作中有这样一个场景:数据库用户名和密码信息放在一个配置文件中,应用读取该配置文件,配置文件信息放入缓存。 若数据库的用户名和密码改变时候,还需要重新加载缓存,比较麻烦,通过Zookeeper可以轻松完成,当数据库发生变化时自动完成缓存同步。

设计思路:

(1)连接zookeeper服务器。

(2)读取zookeeper中的配置信息,注册watcher监听器,存入本地变量。

(3)当zookeeper中的配置信息发生变化时,通过watcher的回调方法捕获数据变化事件。

(4)重新获取配置信息。

6.2 生成分布式唯一ID

在过去的单库单表型系统中,通常可以使用数据库字段自带的auto_increment属性来自动为每条记录生成一个唯一的ID。但是分库分表后,就无法再依靠数据库的auto_increment属性唯一标识一条记录了。此时我们就可以用zookeeper在分布式环境下生成全局唯一ID。

设计思路:

(1)连接zookeeper服务器

(2)指定路径下生成临时有序节点

(3)取序号及为分布式环境下的唯一ID

6.3 分布式锁

分布式锁有多重实现方式,比如通过数据库,redis都可以实现。作为分布式协同工具Zookeeper,当然也有着标准的实现方式。下面介绍在zookeeper中如何实现排它锁。

设计思路:

(1)每个客户端往/Locks下创建临时有序节点/Locks/Lock_,创建成功后/Locks下面会有每个客户端对应的节点。如/Locks/Lock_0000001

(2)客户端取得/Locks下子节点,并进行排序,判断排在最前面的是否为自己,如果自己的锁节点在第一位,代表获取锁成功。

(3)如果自己的锁节点不在第一位,则监听自己前一位的锁节点。如果自己锁节点Lock_000002,那么则监听Lock_0000001。

(4)当前一位锁节点(Lock_000000001)对应的客户端执行完成,释放了锁,将会触发监听客户端(Lock_000002)的逻辑。

(5)监听客户端重新执行第2步逻辑,判断自己是否获得了锁。

7 zookeeper的leader选举

7.1一致性协议

zab协议的全称是Zookeeper Atomic Broadcast (zookeeper原子广播)。zookeeper是通过zab协议来保证分布式事务的最终一致性

基于zab协议,zookeeper集群中的角色主要有一下三类:

  • 领导者(leader):领导者负责进行投票的发起和决议,更新系统状态。
  • 学习者(Learner):
    • Follower:用于接受客户请求并向客户端返回结果,将写请求转发给leader节点,在选举过程中参与投票。
    • ObServer:用于接受客户请求并向客户端返回结果,但是ObServer不参加投票过程,只同步leader的状态。ObServer的目的是为了扩展系统,提高读取速度。
  • 客户端(Client) 请求发起方。

zab广播模式工作原理,通过类似两阶段提交协议的方式解决数据一致性:

(1)leader从客户端收到一个写请求。

(2)leader生成一个新的事务并为这个事务生成一个唯一的ZXID。

(3)leader将这个事务提交(propose)发送给所有的follows节点。

(4)follower节点将收到的事务请求加入到历史队列(history queue)中,并发送ack给leader当leader收到大多数follower(半数以上节点)的ack消息,leader会发送commit请求。当follower收到commit请求时,从历史队列中将事务请求commit。

7.2 zookeeper的leader选举

1、服务器状态

(1)looking:寻找leader状态。当服务器处于该状态时,它会认为当前集群中没有leader,因此需要进入leader选举状态。

(2)leading:领导者状态。表明当前服务器角色是leader。

(3)followin:跟随者状态。表明当前服务器角色是follower。

(4)observing:观察者状态。表明当前服务器角色是observer。

2、服务器启动时期的leader选举

在集群初始化阶段,当有一台服务器server启动时,其单独无法进行完成leader选举,当第二台服务器server2启动时,此时两台机器可以相互通信,每台机器都试图找到leader。于是进入leader选举过程。选举过程如下:

(1)每个server发出一个投票。由于是初始情况,server1和server2都会将自己作为leader服务器进行投票,投票会包含所推举的服务器的myid(服务器的编号)和zxid(事务ID),使用(myid,zxid)来表示,此时server1的投票为(1,0),server2的投票为(2,0),然后各自将这个投票发给集群中其他机器。

(2)集群中的每一台服务器接受来自集群中各个服务器的投票。

(3)处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行pk,pk规则如下:

①优先检查zxid。zxid比较大的服务器优先为leader。

②如果zxid相同,那么就比较myid。myid比较大的服务器作为leader服务器。

对于Server1而言,它的投票是(1,0),接受Server2的投票为(2,0),首先会比较两者的zxid,均为0,再比较myid,此时server2的myid最大,于是更新自己的投票为(2,0),然后重新投票,对于server2而言,其无须更新自己的投票,只是再次向集群中所有机器发出上一次的投票信息即可。

(4)统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,对于server1、server2而言,都统计出集群中已经有两台机器接受了(2,0)的投票信息,此时便认为已经选出了leader。

(5)改变服务状态。一旦确定了leader,每个服务器就会更新自己的状态,如果是follower,那么久变更为following,如果是leader,就变更为leading。

2、服务器运行时期的Leader选举

在zookeeper运行期间,leader与非leader服务器各司其职,即便当有非leader服务器宕机或新加入,此时也不会影响leader,但是一旦leader服务器挂了,那么这个集群将暂停对外服务,进入新一轮leader选举,其过程和启动时期的Leader选举过程基本一致。

假设正在运行的server1、server2、server3三台服务器,当前leader是server2,若某一时刻leader挂了、此时开始Leader选举。选举过程如下:

(1)变更状态。leader挂后,剩余的服务器都会将自己的服务状态变更为looking,然后开始进入leader选举过程。

(2)每个server会发出一个投票。在运行期间,每个服务器上的zxid可能不同,此时假设server1的ZXID为122,server3的zxid为122,在第一轮投票中,server1和server3都会投自己、产生投票(1,122),(3,122),然后各自将投票发送给集群中的所有机器。

(3)接受来自各个服务器的投票。与启动时过程相同。

(4)处理投票。与启动时过程相同,此时,server3将会成为leader。

(5)统计投票。与启动时过程相同。

(6)改变服务器的状态。与启动时过程相同。

7.3 observer角色及其配置

1、observer角色特点

(1)不参与集群的leader选举

(2)不参与集群中写数据时的ack反馈

2、配置observer

为了使用observer角色,在任何想变成observer角色的配置文件中加入如下配置:

peerType=observer

并在所有的server的配置文件中,配置成observer模式的server的哪行配置追加:observer。

例如:

server.3=192.168.10.103:2181:2183:observer

相关文章:

zookeeper-docker版

Zookeeper-docker版 1 zookeeper概述 1.1 什么是zookeeper Zookeeper是一个分布式的、高性能的、开源的分布式系统的协调(Coordination)服务,它是一个为分布式应用提供一致性服务的软件。 1.2 zookeeper应用场景 zookeeper是一个经典的分…...

StableDiffusion本地部署 3 整合包猜想

本地部署和整合包制作猜测 文章目录 本地部署和整合包制作猜测官方部署第一种第二种 StabilityMatrix下载整合包制作流程猜测 写了这么多python打包和本地部署的文章,目的是向做一个小整合包出来,不要求有图形界面,只是希望一键就能运行。 但…...

数据结构(初阶)(七)----树和二叉树(前中后序遍历)

实现链式结构的二叉树 实现链式结构的二叉树遍历前序遍历中序遍历后序遍历 节点个数叶子节点个数⼆叉树第k层结点个数⼆叉树的深度/⾼度查找值为X的节点二叉树的销毁 层序遍历判断二叉树是否为完全二叉树 ⽤链表来表⽰⼀棵⼆叉树,即⽤链来指⽰元素的逻辑关系。 通常…...

SOME/IP 教程知识点总结

总结关于SOME/IP的教程,首先通读整个文件,理解各个部分的内容。看起来这个教程从介绍开始,讲到了为什么在车辆中使用以太网,然后详细讲解了SOME/IP的概念、序列化、消息传递、服务发现(SOME/IP-SD)、发布/订阅机制以及支持情况。 首先,我需要确认每个章节的主要知识点。…...

安装 Windows Docker Desktop - WSL问题

一、关联文章: 1、Docker Desktop 安装使用教程 2、家庭版 Windows 安装 Docker 没有 Hyper-V 问题 3、打开 Windows Docker Desktop 出现 Docker Engine Stopped 问题 二、问题解析 打开 Docker Desktop 出现问题,如下: Docker Desktop - WSL update failed An error o…...

科技赋能筑未来 中建海龙MiC建筑技术打造保障房建设新标杆

近日,深圳梅林路6号保障房项目顺利封顶,标志着国内装配式建筑领域又一里程碑式突破。中建海龙科技有限公司(以下简称“中建海龙”)以模块化集成建筑(MiC)技术为核心,通过科技创新与工业化建造深…...

json介绍、python数据和json数据的相互转换

目录 一 json介绍 json是什么? 用处 Json 和 XML 对比 各语言对Json的支持情况 Json规范详解 二 python数据和json数据的相互转换 dumps() : 转换成json loads(): 转换成python数据 总结 一 json介绍 json是什么? 实质上是一条字符串 是一种…...

关于学习一门新的编程语言的策略

实践 实践 实践 那么如何实践呢 ,very easy,测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测验 测…...

Rust 是什么

Rust 是什么 Rust 是一种由 Mozilla 开发的系统级编程语言,它于 2010 年首次亮相,在 2015 年发布 1.0 版本,此后迅速发展并受到广泛关注。 内存安全:Rust 最大的亮点之一是它在编译阶段就能够避免常见的内存错误,如空指针引用、数据竞争和内存泄漏等。它通过所有权(Owne…...

C#开发——时间间隔类TimSpan

TimeSpan 是 C# 中的一个结构( struct ),用于表示时间间隔或持续时间。它位于 System 命名空间中,是处理时间相关操作时非常重要的工具,尤其是在计算两个日期或时间之间的差值、表示时间段或执行时间相关的运算…...

计算机毕设JAVA——某高校宿舍管理系统(基于SpringBoot+Vue前后端分离的项目)

文章目录 概要项目演示图片系统架构技术运行环境系统功能简介 概要 网络上许多计算机毕设项目开发前端界面设计复杂、不美观,而且功能结构十分单一,存在很多雷同的项目:不同的项目基本上就是套用固定模板,换个颜色、改个文字&…...

[随手笔记]C#保留小数防止四舍五入有效解决办法

private decimal 截断小数(decimal 原小数值, int 保留小数个数) { string 原小数转字符串值 原小数值.ToString(); try { if (原小数转字符串值.Contains(".")) { int 原小数总长度 原小数转字符串值.Length; …...

C++ 二叉树代码

二叉树代码&#xff0c;见下 #include <iostream> using namespace std;template<typename T> struct TreeNode{T val;TreeNode *left;TreeNode *right;TreeNode():val(0), left(NULL), right(NULL)TreeNode(T x):val(x), left(NULL), right(NULL){} };template&l…...

Spring Boot 测试:单元、集成与契约测试全解析

一、Spring Boot 分层测试策略 Spring Boot 应用采用经典的分层架构&#xff0c;不同层级的功能模块对应不同的测试策略&#xff0c;以确保代码质量和系统稳定性。 Spring Boot 分层架构&#xff1a; Spring Boot分层架构 A[客户端] -->|HTTP 请求| B[Controller 层] …...

Oracle 数据库基础入门(四):分组与联表查询的深度探索(上)

在 Oracle 数据库的学习进程中&#xff0c;分组查询与联表查询是进阶阶段的重要知识点&#xff0c;它们如同数据库操作的魔法棒&#xff0c;能够从复杂的数据中挖掘出有价值的信息。对于 Java 全栈开发者而言&#xff0c;掌握这些技能不仅有助于高效地处理数据库数据&#xff0…...

机器学习的起点:线性回归Linear Regression

机器学习的起点&#xff1a;线性回归Linear Regression 作为机器学习的起点&#xff0c;线性回归是理解算法逻辑的绝佳入口。我们从定义、评估方法、应用场景到局限性&#xff0c;用生活化的案例和数学直觉为你构建知识框架。 回归算法 一、线性回归的定义与核心原理 定义&a…...

2024贵州大学计算机考研复试上机真题

历年贵州大学计算机考研复试上机真题 2024贵州大学计算机考研复试上机真题 2023贵州大学计算机考研复试上机真题 贵州大学计算机考研复试上机真题 在线 oj 测评&#xff1a;https://app2098.acapp.acwing.com.cn/problem/list/ 字符串翻转 题目描述 给定一个字符串&#xf…...

17、什么是智能指针,C++有哪几种智能指针【高频】

智能指针其实不是指针&#xff0c;而是一个&#xff08;模板&#xff09;类&#xff0c;用来存储指向某块资源的指针&#xff0c;并自动释放这块资源&#xff0c;从而解决内存泄漏问题。主要有以下四种&#xff1a; auto_ptr 它的思想就是当当一个指针对象赋值给另一个指针对…...

PyCharm接入本地部署DeepSeek 实现AI编程!【支持windows与linux】

今天尝试在pycharm上接入了本地部署的deepseek&#xff0c;实现了AI编程&#xff0c;体验还是很棒的。下面详细叙述整个安装过程。 本次搭建的框架组合是 DeepSeek-r1:1.5b/7b Pycharm专业版或者社区版 Proxy AI&#xff08;CodeGPT&#xff09; 首先了解不同版本的deepsee…...

深入解析SQL Server高级SQL技巧

SQL Server 是一种功能强大的关系型数据库管理系统&#xff0c;广泛应用于各种数据驱动的应用程序中。在开发过程中&#xff0c;掌握一些高级SQL技巧&#xff0c;不仅能提高查询性能&#xff0c;还能优化开发效率。这篇文章将全面深入地探讨SQL Server中的一些高级技巧&#xf…...

PyCharm怎么集成DeepSeek

PyCharm怎么集成DeepSeek 在PyCharm中集成DeepSeek等大语言模型(LLM)可以借助一些插件或通过代码调用API的方式实现,以下为你详细介绍两种方法: 方法一:使用JetBrains AI插件(若支持DeepSeek) JetBrains推出了AI插件来集成大语言模型,不过截至2024年7月,官方插件主要…...

Hive之正则表达式RLIKE详解及示例

目录 一、RLIKE 语法及核心特性 1. 基本语法 2. 核心特性 二、常见业务场景及示例 场景1&#xff1a;过滤包含特定模式的日志&#xff08;如错误日志&#xff09; 场景2&#xff1a;验证字段格式&#xff08;如邮箱、手机号&#xff09; 场景3&#xff1a;提取复杂文本中…...

fluent-ffmpeg 依赖详解

fluent-ffmpeg 是一个用于在 Node.js 环境中与 FFmpeg 进行交互的强大库&#xff0c;它提供了流畅的 API 来执行各种音视频处理任务&#xff0c;如转码、剪辑、合并等。 一、安装 npm install fluent-ffmpeg二、基本使用 要使用 fluent-ffmpeg&#xff0c;首先需要确保系统中…...

【定昌Linux系统】部署了java程序,设置开启启动

将代码上传到相应的目录&#xff0c;并且配置了一个.sh的启动脚本文件 文件内容&#xff1a; #!/bin/bash# 指定JAR文件的路径&#xff08;如果JAR文件在当前目录&#xff0c;可以直接使用文件名&#xff09; JAR_FILE"/usr/local/java/xs_luruan_client/lib/xs_luruan_…...

Java零基础入门笔记:(7)异常

前言 本笔记是学习狂神的java教程&#xff0c;建议配合视频&#xff0c;学习体验更佳。 【狂神说Java】Java零基础学习视频通俗易懂_哔哩哔哩_bilibili 第1-2章&#xff1a;Java零基础入门笔记&#xff1a;(1-2)入门&#xff08;简介、基础知识&#xff09;-CSDN博客 第3章…...

【字符串】最长公共前缀 最长回文子串

文章目录 14. 最长公共前缀解题思路&#xff1a;模拟5. 最长回文子串解题思路一&#xff1a;动态规划解题思路二&#xff1a;中心扩散法 14. 最长公共前缀 14. 最长公共前缀 ​ 编写一个函数来查找字符串数组中的最长公共前缀。 ​ 如果不存在公共前缀&#xff0c;返回空字符…...

【软路由】ImmortalWrt 编译指南:从入门到精通

对于喜欢折腾路由器&#xff0c;追求极致性能和定制化的玩家来说&#xff0c;OpenWrt 无疑是一个理想的选择。而在众多 OpenWrt 衍生版本中&#xff0c;ImmortalWrt 以其更活跃的社区、更激进的特性更新和对新硬件的支持而备受关注。 本文将带你深入了解 ImmortalWrt&#xff0…...

react 中,使用antd layout布局中的sider 做sider的展开和收起功能

一 话不多说&#xff0c;先展示效果&#xff1a; 展开时&#xff1a; 收起时&#xff1a; 二、实现代码如下 react 文件 import React, {useState} from react; import {Layout} from antd; import styles from "./index.module.less"; // 这个是样式文件&#…...

easyExcel使用案例有代码

easyExcel 入门,完成web的excel文件创建和导出 easyExcel官网 EasyExcel 的主要特点如下&#xff1a; 1、高性能&#xff1a;EasyExcel 采用了异步导入导出的方式&#xff0c;并且底层使用 NIO 技术实现&#xff0c;使得其在导入导出大数据量时的性能非常高效。 2、易于使…...

CPU、SOC、MPU、MCU--详细分析四者的区别

一、CPU 与SOC的区别 1.CPU 对于电脑&#xff0c;我们经常提到&#xff0c;处理器&#xff0c;内存&#xff0c;显卡&#xff0c;硬盘四大部分可以组成一个基本的电脑。其中的处理器——Central Processing Unit&#xff08;中央处理器&#xff09;。CPU是一台计算机的运算核…...