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成功,因為可以看看上面的注意,是一個補償機制