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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/71094.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/71094.shtml
英文地址,請注明出處:http://en.pswp.cn/web/71094.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【量化金融自學筆記】--開篇.基本術語及學習路徑建議

在當今這個信息爆炸的時代,金融領域正經歷著一場前所未有的變革。傳統的金融分析方法逐漸被更加科學、精準的量化技術所取代。量化金融,這個曾經高不可攀的領域,如今正逐漸走進大眾的視野。它將數學、統計學、計算機科學與金融學深度融合&…

unity學習56:舊版legacy和新版TMP文本輸入框 InputField學習

目錄 1 舊版文本輸入框 legacy InputField 1.1 新建一個文本輸入框 1.2 InputField 的子物體構成 1.3 input field的的component 1.4 input Field的屬性 2 過渡 transition 3 控件導航 navigation 4 占位文本 placeholder 5 文本 text 5.1 文本內容,用戶…

汽車電子電控軟件開發中因復雜度提升導致的架構惡化問題

針對汽車電子電控軟件開發中因復雜度提升導致的架構惡化問題,建議從以下方向進行架構優化和開發流程升級,以提升靈活性、可維護性和擴展性: 一、架構設計與模塊化優化 分層架構與模塊解耦 采用AUTOSAR標準的分層架構(應用層、運行…

【彈性計算】彈性裸金屬服務器和神龍虛擬化(一):功能特點

彈性裸金屬服務器和神龍虛擬化(一):功能特點 特征一:分鐘級交付特征二:兼容 VPC、SLB、RDS 等云平臺全業務特征三:兼容虛擬機鏡像特征四:云盤啟動和數據云盤動態熱插拔特征五:虛擬機…

騰訊云大模型知識引擎驅動的DeepSeek滿血版醫療顧問大模型搭建實戰

文章目錄 1. 引言2. 什么是騰訊云大模型知識引擎(LKE)?核心優勢功能特點應用場景 3. 模型搭建過程3.1 注冊登錄產品3.2 創建應用3.3 配置模型3.4 配置角色指令3.5 配置歡迎語3.6 配置知識庫3.7 配置工作流3.8 啟用聯網搜索3.9 發布模型 4. 問…

nio中ByteBuffer使用

創建ByteBuffer ByteBuffer buffer ByteBuffer.allocate(10);// 字符串轉 bytebufferByteBuffer buffer01 Charset.defaultCharset().encode("hello world"); ByteBuffer buffer02 ByteBuffer.wrap("hello".getBytes()); ByteBuffer buffer03 Standard…

如何在 IntelliJ IDEA 中集成 DeepSeek

如何在 IntelliJ IDEA 中集成 DeepSeek 在本教程中,我們將帶您一步步完成將 DeepSeek 集成到 IntelliJ IDEA 中的過程。通過此集成,您可以在IDE中利用DeepSeek強大的功能,提高開發工作效率。 步驟 1:安裝 Proxy AI 插件 首先&a…

【Maven】入門介紹 與 安裝、配置

文章目錄 一、Maven簡介1. Maven介紹2. Maven軟件工作原理模型圖 二、Maven安裝和配置1. Maven安裝2. Maven環境配置3. Maven功能配置4. IDEA配置本地Maven軟件 一、Maven簡介 1. Maven介紹 https://maven.apache.org/what-is-maven.html Maven 是一款為 Java 項目管理構建、…

Java數據結構第十六期:走進二叉樹的奇妙世界(五)

專欄:Java數據結構秘籍 個人主頁:手握風云 目錄 一、非遞歸實現遍歷二叉樹 1.1. 二叉樹的前序遍歷 1.2. 二叉樹的中序遍歷 1.3. 二叉樹的后序遍歷 一、非遞歸實現遍歷二叉樹 1.1. 二叉樹的前序遍歷 我們這里要使用棧來進行實現。我們反向思考一下為…

算法004——盛最多水的容器

力扣——盛最多水的容器點擊即可跳轉 當我們選擇1號線和8號線時,下標為 1 和 8 形成容器的容積的高度是由 較矮的決定的,即下標為 8 的位置; 而寬度則是 1到8 之間的距離,為 8-17,此時容器的容積為 7 * 7 49。 當我…

算法-二叉樹篇26-將有序數組轉換為二叉搜索樹

將有序數組轉換為二叉搜索樹 力扣題目鏈接 題目描述 給你一個整數數組 nums ,其中元素已經按 升序 排列,請你將其轉換為一棵 平衡 二叉搜索樹。 解題思路 很簡單的遇到遞歸題目,對數組取半,然后構建中間節點作為該數組對應的…

十一、Spring Boot:使用JWT實現用戶認證深度解析

Spring Boot JWT(JSON Web Token):無狀態認證 在現代 Web 開發中,無狀態認證是一種重要的安全機制,它允許服務器在不存儲會話信息的情況下驗證用戶身份。JSON Web Token(JWT)是一種常用的無狀態…

MIT何愷明再次突破傳統:分形遞歸架構引爆生成模型新紀元!

論文鏈接:https://arxiv.org/pdf/2502.17437 代碼鏈接:https://github.com/LTH14/fractalgen 亮點直擊 分形生成模型:首次將分形理論引入生成模型,提出了一種具有自相似性的遞歸生成框架。 遞歸模塊化:通過遞歸調用生…

用Python之requests庫調用大型語言模型(LLM)API的流式輸出與非流式輸出比較

文章目錄 1. 非流式輸出與流式輸出概述2. 非流式輸出2.1 代碼實例12.2 代碼實例2 3. 流式輸出3.1 流式輸出的定義和作用3.2 流式輸出適用的場景3.3 流式輸出的實現方式與實現技術3.4 代碼實例33.5 代碼實例4 4. 小結 1. 非流式輸出與流式輸出概述 大模型收到輸入后并不是一次性…

大模型技術:重塑未來的力量

大模型技術之所以成為當今科技領域的熱點,是因為它擁有改變游戲規則的能力。以ChatGPT為例,這款由OpenAI開發的大型語言模型,首次實現了基于語言的智能涌現,推動了通用人工智能的技術飛躍和快速進化。大模型通過強大的數據處理能力…

【朝夕教育】《鴻蒙原生應用開發從零基礎到多實戰》005-TypeScript 中的枚舉

標題詳情作者簡介愚公搬代碼頭銜華為云特約編輯,華為云云享專家,華為開發者專家,華為產品云測專家,CSDN博客專家,CSDN商業化專家,阿里云專家博主,阿里云簽約作者,騰訊云優秀博主&…

框架模塊說明 #09 日志模塊_02

背景 上篇我們介紹了系統日志處理方式,也結合我們實際和日志系統集成的需求,將我們的日志文件配置成json格式。這次我們針對我們操作日志的處理進行一些介紹。 還是采用傳統的aop的形式進行操作日志的保存,并按業務類型進行定義保存到mongodb…

DeepSeek-R1自寫CUDA內核跑分屠榜:開啟GPU編程自動化新時代

引言 在AI領域,深度學習模型的性能優化一直是研究者們關注的核心。最近,斯坦福和普林斯頓的研究團隊發現,DeepSeek-R1生成的自定義CUDA內核不僅超越了OpenAI的o1和Claude 3.5 Sonnet,還在KernelBench框架中取得了總排名第一的好成…

記Android12上一個原生bug引起的system_server crash

歡迎使用Markdown編輯器 一. 現象描述 近日測試上報一個幾乎必現的crash,描述如下: 現象: launcher編輯狀態與鎖屏解鎖交互時系統概率性重啟 操作步驟: 進入launcher組件編輯狀態按電源鍵滅屏后亮屏,鎖屏界面上滑解鎖launcher編輯狀態向右或向左滑動重…

系統架構設計師—計算機基礎篇—計算機體系結構

文章目錄 計算機硬件分級存儲體系目的特點 硬件組成CPU運算器控制器 主存儲器 指令系統流水線 內存按字節編址磁盤陣列 計算機硬件 分級存儲體系 寄存器組(CPU)Cache(內存)主存Flash(外存/輔存) 目的 解…