Zookeeper是能夠存儲數據的,因此咱們能夠把它理解一個數據庫,實際上它的底層原理自己也和數據庫是相似的。node
咱們知道,數據庫是用來存儲數據的,只是數據能夠存儲在內存中或磁盤中。而Zookeeper實際是結合了這兩種的,Zookeeper中的數據即會存儲在磁盤中以達到持久化的目的,也會同步到內存中以到達快速訪問的目的。sql
事實上,用過Zookeeper的同窗應該知道,Zookeeper中有兩種類型的節點:持久化節點和臨時節點。數據庫
做爲一個數據庫,確定是要接收客戶端建立、修改、刪除、查詢節點等請求的。服務器
在Zookeeper中對於請求分爲兩類:微信
Zookeeper一般都是以集羣模式運行的,也就是Zookeeper集羣中各個節點的數據須要保持一致的。可是和Mysql集羣不同的是:異步
Zookeeper集羣底層是怎麼保證數據一致性的,實際上是用的兩階段提交+過半機制來保證的,後面會單獨寫一篇文章來介紹這個的底層實現,感興趣的能夠關注一下個人微信公衆號:1點25學習
事務性請求包括:更新操做、新增操做、刪除操做,結合上面的分析,由於這些操做是會影響數據的,因此要保證這些操做在整個集羣內的事務性,因此這些操做就是事務性請求。日誌
那麼非事務性請求就好理解的,像查詢操做、exist操做這些不影響數據的操場,就不須要集羣來保持事務性,因此這些操場就是非事務性請求。code
Zookeeper在處理事務性請求時,比處理非事務性請求要複雜不少cdn
假設咱們如今在Zookeeper中有一個數據節點,節點名爲/datanode
,內容爲125
,該節點是持久化節點,因此該節點信息會保存在文件中。
可能你們都會認爲是相似下面這樣方式保存在磁盤文件中的,方法一:
節點名 | 節點內容 |
---|---|
/datanode | 125 |
可是除開這種表示方法,還有另一種表示方法,快照+事務日誌,好比方法二:
當前快照:
節點名 | 節點內容 |
---|---|
/datanode | 120 |
當前事務日誌:
事務ID | 操做 | 節點名 | 節點內容修改前 | 節點內容修改後 |
---|---|---|---|---|
1000010 | update | /datanode | 120 | 121 |
1000011 | update | /datanode | 121 | 125 |
乍一看方法二比方法一要更復雜,而且佔用的磁盤更多。可是咱們上文提到過,Zookeeper集羣中的節點在處理事務性請求時,須要將事務操做同步給其餘節點,因此這裏的事務操做是必定要進行持久化的,以便在同步給其餘節點時出現異常進行補償。因此就出現了事務日誌。實際上事務日誌還運行數據進行回滾,這個在兩階段提交中也是很是重要的。
那麼快照又有什麼用呢?事務日誌必定要有,可是隨着時間的推移,日誌確定會愈來愈多,因此確定不能持久化歷史上全部的日誌,因此Zookeeper會定時的進行快照,並刪除以前的日誌。
那麼若是按方法二這麼存儲數據,在對數據進行查詢時就不太方便了。上文說到,Zookeeper爲了提升數據的查詢速度,會在內存中也存儲一份數據,那麼內存中的這份數據又該怎麼存呢?
Zookeeper中的數據在內存中的表示其實和上文的方法一很相似,只是Zookeeper中的數據是具備文件目錄特色的,說白了就是Zookeeper中的數據節點的名字必定要以「/」
開頭,這樣就致使Zookeeper中的數據相似一顆樹:
一顆具備父子層級的多叉樹,在Zookeeper源碼中叫DataTree。
請看下圖:
請注意,對於上圖,Zookeeper真正的底層實現,zk1是Leader,zk2和zk3是Learner,是根據領導者選舉選出來的。
非事務性請求直接讀取DataTree上的內容,DataTree是在內存中的,因此會很是快。
這篇文章介紹了Zookeeper在處理請求時的幾個核心概念:
下篇文章來詳細的介紹一下Zookeeper處理請求時二階段提交是如何實現的。
有痛點纔有創新,一個技術確定都是爲了解決某個痛點纔出現的。 請幫忙轉發一下,若是想第一時間學習更多的精彩的內容,請關注微信公衆號:1點25