有用過Zookeeper的都知道zoo.cfg配置文件中有dataDir配置項用於存儲數據,不過可能有些人不太清楚這個目錄具體存儲的是那些數據,默認狀況下這個目錄是用於存儲Log(事務日誌)與Snapshot(快照)數據,可是Zookeeper還提供了一個用於Log存儲目錄的配置項dataLogDir而dataDir用於存儲Snapshot數據,Log文件寫入頻率很是高若是有對Snapshot文件常常操做或是對Zookeeper性能要求很是高能夠爲Log與Snapshot分別配置不一樣的目錄存儲;本文主要是結合源碼分析Zookeeper的Log與Snapshot文件,這裏我分別爲Log與Snapshot配置了不一樣的存儲目錄:dataDir=D:/zookeeper-3.4.6/data 、dataLogDir=D:/zookeeper-3.4.6/data/log;
事務日誌與Snapshot的操做是在org.apache.zookeeper.server.persistence包中,這裏也主要是分析該包下的各個類;在FileTxnSnapLog類中看到了它在咱們爲事務日誌與Snapshot配置的目錄下又建立了一個子目錄version-2同時又指定爲該兩種文件的存儲目,在裏面還能夠看到FileTxnLog、FileSnap類分別爲處理事務日誌和Snapshot的;java
在Zab協議中咱們知道每當有接收到客戶端的事務請求後Leader與Follower都會將把該事務日誌存入磁盤日誌文件中,該日誌文件就是這裏所說的事務日誌,下面將詳細分析該日誌文件;
FileTxnLog類用於處理事務日誌文件這裏就今後類開始,在該類中看到了preAllocSize、TXNLOG_MAGIC、VERSION、lastZxidSeen、dbId等這樣的屬性:
1. preAllocSize: 默認預分配的日誌文件的大小65536*1024字節
2. TXNLOG_MAGIC:日誌文件魔數爲ZKLG
3. VERSION:日誌文件版本號2
4. lastZxidSeen:最後的ZXIDapache
類中還有一個靜態代碼塊用於讀取配置項中的preAllocSize,也就是說預分配的日誌文件大小是可配置的,接下來看看該類中最重要的一個方法append,該方法主要功能是建立新的日誌文件與往日誌文件中追加新的事務日誌記錄;從中能夠看到日誌文件的相關信息:api
1. 文件名爲log,後綴爲十六進制的ZXID
2. 日誌文件頭有:magic、version、dbid
3. 建立文件後分配的文件大小爲:67108864字節+16字節,其中16字節爲文件頭
4. 使用Adler32做爲日誌文件的校驗碼
5. 當日志文件寫滿預分配大大小後就擴充日誌文件一倍大小session
1.1 日誌文件目錄數據結構
正如從代碼中看到的同樣version-2目錄中存儲着Zookeeper的事務日誌文件,有看到log.十、log.4f文件,這些都是Zookeeper的事務日誌文件;這兩個文件都有一個特色就是文件名爲log.xx,大小爲64MB文件的後綴xx時間最先的 數字老是比最晚的小。若是有了解過Zookeeper的ZAB協議那確定知道它爲每個事務請求都分配了一個事務ID也就是ZXID,上面章節也知道了xx就是Zookeeper處理請求的ZXID,該ZXID爲log文件中第一條事務的ZXID;ZXID規則爲前32 字節爲Leader週期,後32字節爲事務請求序列,因此經過事務日誌就能夠輕鬆的知道當前的Leader週期與每一個文件所屬的Leader週期;app
日誌文件可視化
事務日誌文件中存儲的都是二進制的數據,若是不借助其餘工具是很難知道里面存儲的內容的,Zookeeper也給咱們提供了這樣的工具,在org.apache.zookeeper.server包中的LogFormatter類爲咱們提供了把事務日誌文件以咱們看得懂的數據輸出的功能,這裏就使用該工具輸出該事務日誌文件,並解釋該數據;
LogFormatter工具的使用方法: java -cp ../../../zookeeper-3.4.6.jar:../../../lib/slf4j-api-1.6.1.jar org.apache.zookeeper.server.LogFormatter log.1工具
日誌分析:
第一行:ZooKeeper Transactional Log File with dbid 0 txnlog format version 2
上面的代碼分析中有說到每一個日誌文件都有一個這就是那裏所說的日誌頭,這裏magic沒有輸出,只輸出了dbid還有version;源碼分析
第二行:15-8-12 下午03時59分53秒 session 0x14f20ea71c10000 cxid 0x0 zxid 0x1 createSession 4000
這也就是具體的事務日誌內容了,這裏是說xxx時間有一個sessionid爲0x14f20ea71c10000、cxid爲0x0、zxid爲0x一、類型爲createSession、超時時間爲4000毫秒性能
第三行:15-8-12 下午03時59分54秒 session 0x14f20ea71c10000 cxid 0x1 zxid 0x2 create '/solinx0000000000,#736f6c696e78,v{s{31,s{'world,'anyone}}},F,1
sessionID爲0x14f20ea71c10000,cxid:0x0一、zxid:0x0二、建立了一個節點路徑爲:/solinx0000000000、節點內容爲:#736f6c696e78(通過ASCII,實際內容爲solinx)、acl爲world:anyone任何人均可以管理該節點、節點不是ephemeral節點的、父節點子版本:1日誌
第四行:15-8-12 下午04時15分56秒 session 0x14f20ea71c10000 cxid 0x0 zxid 0x3 closeSession null
這裏是說xxx時間有一個sessionid爲0x14f20ea71c10000、cxid爲0x0、zxid爲0x三、類型爲closeSession
快照文件的處理在FileSnap類中,與事務日誌文件同樣快照文件也同樣有SNAP_MAGIC、VERSION、dbId這些,這做用也只是用來標識這是一個快照文件;Zookeeper的數據在內存中是以DataTree爲數據結構存儲的,而快照就是每間隔一段時間Zookeeper就會把整個DataTree的數據序列化而後把它存儲在磁盤中,這就是Zookeeper的快照文件,快照文件是指定時間間隔對數據的備份,因此快照文件中數據一般都不是最新的,多久抓一個快照這也是能夠配置的snapCount配置項用於配置處理幾個事務請求後生成一個快照文件;
與事務日誌文件同樣快照文件也是使用ZXID做爲快照文件的後綴,在FileTxnSnapLog類中的save方法中生成文件並調用FileSnap類序列化DataTree數據而且寫入快照文件中;
1.2 快照文件目錄
快照文件可視化
與日誌文件同樣Zookeeper也爲快照文件提供了可視化的工具org.apache.zookeeper.server包中的SnapshotFormatter類,接下來就使用該工具輸出該事務日誌文件,並解釋該數據;
SnapshotFormatter工具的使用方法: java -cp ../../zookeeper-3.4.6.jar:../../lib/slf4j-api-1.6.1.jar org.apache.zookeeper.server.SnapshotFormatter snapshot.17
快照分析
快照文件就很容易看得懂了,這就是Zookeeper整個節點數據的輸出;
第一行:ZNode Details (count=11):
ZNode節點數總共有11個
/cZxid = 0x00000000000000
ctime = Thu Jan 01 08:00:00 CST 1970
mZxid = 0x00000000000000
mtime = Thu Jan 01 08:00:00 CST 1970
pZxid = 0x00000000000016
cversion = 7
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x00000000000000
dataLength = 0
這麼一段數據是說,根節點/:
cZxid:建立節點時的ZXID
ctime:建立節點的時間
mZxid:節點最新一次更新發生時的zxid
mtime:最近一次節點更新的時間
pZxid:父節點的zxid
cversion:子節點更新次數
dataVersion:節點數據更新次數
aclVersion:節點acl更新次數
ephemeralOwner:若是節點爲ephemeral節點則該值爲sessionid,不然爲0
dataLength:該節點數據的長度
快照文件的末尾: Session Details (sid, timeout, ephemeralCount): 0x14f211584840000, 4000, 0 0x14f211399480001, 4000, 0 這裏是說當前抓取快照文件的時間Zookeeper中Session的詳情,有兩個session超時時間都是4000毫秒ephemeral節點爲0;