1. 程式人生 > 實用技巧 >zookeeper原理

zookeeper原理

什麼是一致性:

要站在叢集的角度去思考問題:

一致性的分類:

強一致性:它要求系統寫入什麼,讀出來的

弱一致性:不承諾立即可以讀到寫入的值,也不久承諾多久之後資料能夠達到一致,但會盡可能地保證
到某個時間級別(比如秒級別)後,資料能夠達到一致狀態。 最終一致性: 系統會保證在一定時間內,能夠達到一個數據一致的狀態。 它是弱一致性中非常推崇的一種一致性模型,也是業界在大型分散式系統的資料一致性上比較推崇的模型。

注意:zookeeper儘量達到強一致性,但是實際上只實現了最終一致性

什麼是2pc

二階段提交(Two-phaseCommit)

2PC是一個非常經典的強一致、中心化的原子提交協議

先由一方進行提議(propose)並收集其他節點的反饋(vote),再根據反饋決定提交(commit)或中止(abort)事務。
我們將提議的節點稱為協調者(coordinator),其他參與決議節點稱為參與者(participants, 或cohorts)

第一階段:

coordinator發起一個提議,分別問詢各participant是否接受。

第二個階段

coordinator根據participant的反饋,提交或中止事務,如果participant全部同意則提交,只要有一個participant不同意就中止。

zookeeper中的一致性:------Zab協議

 Zookeeper Atomic Broadcast (Zookeeper原子廣播)。
Zookeeper 是通過 Zab 協議來保證分散式事務的最終一致性。

1:Leader-------選舉過程

2:2pc---------------過程

3:過半機制-驗證是不是超過一半

4:同步過程-----------發生機制

Leader領導者選舉

至少要兩臺zk,才會有選舉

zookeeper的資料儲存:

記憶體---每個zk都有一個ZkDatabase物件,

磁碟----Database物件持久化到磁碟

請求的過程:

1收到一個create /quan  123請求後


2會先生成一個日誌
------持久化到磁碟 (使用的是追加模式,速度快) 3指定操作記憶體中的資料----DataBase

注意,我們很多資料庫都是靠日誌來恢復資料的

create /quan 123

set /quan 234

set /quan 345

這樣子其實有些日誌是不需要追加的,導致日誌越來越大

解決:

zk有有個單獨的執行緒,去定時將記憶體中的資料進行快照

快照就是將記憶體中的DataBase存到DataBase檔案裡面去

就在這個時候,會把日誌刪除掉

Leader的特徵:

1-資料最新

因為上面我們知道處理資料之前,我們都是先進行日誌追加,而日誌追加的內容

有一個zxid,是一個自增的id,

這就意味著zxid越大,表示處理的資料是越多的,那叢集裡面應該是最新的

第二種情況:

當zxid都是一致的時候,比較myid,最大的選為leader

zk的投票過程:

11111

伺服器剛剛啟動的時候,投的票都是自己
zookeeper裡面存在一個hash表,儲存的是投票資訊zxid,myid
所以一開始都是寫自己的資訊

222222,傳送自己的投票資訊,

當投票完自己之後,需要進行叢集之間的交流,伺服器之間要建立socket連線

zookeeper的原始碼裡面定義了我去連的zk的myid必須要比自己的小才能建立socket連線
這樣子避免了建立多條連線

3333比較收到的投票資訊

4444

我們如果只有3臺zk,那麼現在就可以知道leader是誰了,因為zk有一個過半機制

555如果這個時候zk3啟動

zk3也會先投票給自己
然後想zk1 zk2其他伺服器傳送自己的投票資訊,
而其他伺服器已經知道自己的角色了,所以直接都返回leader是誰的資訊給zk3

最後其實zk3可以直接知道自己的角色是follower.

6666zk3知道自己是follower後,會和leader建立一個數據同步的socket連線

所以可以知道其實每一臺zk都會啟動三個埠,一個是leader選舉埠,一個是資料同步+心跳埠

最後一個是zk客戶端連線埠

注意:即使zk3的zxid為200,也不會是leader,而zk裡面會直接將zk3進行回滾(可以這麼理解),其實就是資料同步

出現這個情況的場景就是,leader處理完一個數據之後,還沒來得及通知其他zk,就已經dea掉了。所以這個資料應該

當重新啟動的時候,其他線上的zk可能處理了其他請求,所以zk裡面原則就是後來則follower

領導者選舉發送的場景:

剛開始啟動叢集的時候

leader-down的時候

超過一半的叢集內的機器掛掉的時候

注意:leader可以通過socket連線進行心跳檢測,知道多少臺follower線上,炒股一半的時候,會自發shutdown

特殊場景11

這時候其實zk2還是在選舉的過程,
所以會新建socket連線去繼續選舉

2-處理資料

1客戶端傳送處理資料請求給leader
2leader會生成日誌,並將日誌傳送給follower,同時開啟一個死迴圈
3死迴圈的內容就是接收所有follower響應回來的ack數量,一旦數量 超過叢集的一半(過半機制),leader就認為整個叢集都可以處理整個請求了
4follower接收到這個日誌之後,進行持久化,並返回ack給leader
5當leader接收到的ack數量過半,leader就進行資料的處理commit
6傳送commit的請求給follower,
7follower接收到請求後,更新自己的database

特殊情況:

1當ack傳送失敗

leader會一直在等待,因為在原始碼裡面,有一個laenerHandler執行緒會一直在等

不會報什麼異常,但是因為客戶端和leader的連線有timeout,所以客戶端會超時

注意:

follower傳送心跳的時候,會攜帶自己的zxid,leader會返回給follower當前你的zxid是大了還是小了還是相等

小了就進行同步

非同步模式

傳送commit的時候,其實是想將訊息傳送新增到一個佇列裡面,然後開啟一個新的執行緒去從佇列裡面

取出訊息併發送

並不會取關心follower是否commit成功,因為可以看看上面的注意,是一個補償機制