Zookeeper是個(gè)in-memory的文件系統(tǒng),類 ZKDatabase
是zk的存儲(chǔ)模塊,類中主要有以下成員:
- DataTree dataTree
數(shù)據(jù)庫棘劣,主要存儲(chǔ)了節(jié)點(diǎn)信息,所有節(jié)點(diǎn)均放在DataTree#nodes
中俗或,節(jié)點(diǎn)信息發(fā)生變化時(shí)溶诞,會(huì)觸發(fā)類內(nèi)部的IWatchManager
對(duì)象通知給客戶端荞下,這是我們常用的功能。
- ConcurrentHashMap<Long, Integer> sessionsWithTimeouts
臨時(shí)節(jié)點(diǎn)在會(huì)話結(jié)束后需要清除隐岛,所以需要有這個(gè)會(huì)話列表猫妙。
- FileTxnSnapLog snapLog
類似于redis的AOF日志。每有一個(gè)請(qǐng)求過來直接附加到一個(gè)日志中
- Long minCommittedLog聚凹,maxCommittedLog
最小和最大的提案zxid割坠,leader內(nèi)存中緩存一部分寫請(qǐng)求log,如果節(jié)點(diǎn)加入了一個(gè)集群妒牙,這兩個(gè)值在leader記錄的范圍內(nèi)彼哼,那么直接sync這部分差異內(nèi)容就可以了,便于快速加入集群湘今。
zookeeper的具體數(shù)據(jù)由snapshot文件存儲(chǔ),snapshot的文件按照順序由以下幾個(gè)部件組成
- 標(biāo)志信息
Int 固定字符"ZKSN"
Int 版本號(hào)
Long 數(shù)據(jù)庫id
- session信息
Int session的數(shù)量sessionCout
接下來是sessionCount 個(gè)session的超時(shí)信息敢朱,每個(gè)的內(nèi)容如下
Long sessionId
Int sessionTime
-- acls權(quán)限信息
Int acl數(shù)量
接下來是aclCount 個(gè)acl,每個(gè)的內(nèi)容如下
Long index
Int perms
String scheme
String id
- 數(shù)據(jù)節(jié)點(diǎn)信息
若干個(gè)node節(jié)點(diǎn)摩瞎,每個(gè)節(jié)點(diǎn)信息如下:
String path (""為root節(jié)點(diǎn),"/"的情況下說明讀取完畢)
String data
Long acl的index
狀態(tài)信息:
Long czxid,mzxid,ctime,mtime
Int version,cversion,aversion
Long ephemeralOwner,pzxid
注意蔫饰,snap中不需要存儲(chǔ)節(jié)點(diǎn)間的關(guān)系,因?yàn)楦鶕?jù)他們的path路徑可以很直接的找到他們的關(guān)系愉豺。其中,有種特別的節(jié)點(diǎn)類型茫因,path是/zookeeper/quota/${realpath}/zookeeper_limits蚪拦。
他們的data用來存儲(chǔ)realpath的限制信息(子節(jié)點(diǎn)的data大小和數(shù)量)。
snap文件dump的時(shí)機(jī)
1.learner(follower和Observer)從leader處同步到數(shù)據(jù)的時(shí)候冻押。(分兩種情況驰贷,DIFF方式,即增量模式不需要洛巢, SNAP模式括袒,即全量時(shí)要)
2.啟動(dòng)時(shí),如果有l(wèi)og文件稿茉,合并完成以后重新生成snapshot文件.
數(shù)據(jù)庫的維護(hù)
1.合并邏輯
由于有l(wèi)og文件的存在锹锰,log文件并沒有及時(shí)merge到數(shù)據(jù)庫文件中,因此存儲(chǔ)實(shí)際數(shù)據(jù)的snapshot文件并不一定是最新的漓库。在zk啟動(dòng)時(shí)有以下步驟:1.加載最新的一個(gè)snapshot文件恃慧;2.調(diào)用fastForwardFromEdits
將log文件的更改merge到內(nèi)存中,并生成commitlog廣播給其他節(jié)點(diǎn)。 3.重新生成干凈的snapshot文件渺蒿。
為方便管理痢士,log文件和snapshot文件均以當(dāng)前文件的最新zxid作為后綴。
2.舊文件清除
類DatadirCleanupManager用來定時(shí)清除log文件和snapshot文件茂装。每次定時(shí)任務(wù)執(zhí)行以下邏輯:
- 保留snapshot文件(最少3個(gè))怠蹂,并取得保留的snapshot中最舊的zxid善延。
- 將后綴小于這個(gè)zxid的snapshot文件和log文件都刪除。
如果日志但是未提交城侧,這條寫操作是否生效易遣?
分為兩種情況討論
日志未被寫到過半節(jié)點(diǎn)
因?yàn)橹灰x舉完成,數(shù)據(jù)就是以新的leader為準(zhǔn)赞庶,如果
1.如果數(shù)據(jù)沒有廣播到過半節(jié)點(diǎn)训挡,那么數(shù)據(jù)在記錄了日志的節(jié)點(diǎn)均沒有參與選舉的情況下集群達(dá)到了一個(gè)新的紀(jì)元的情況下可能丟失:
由以下幾點(diǎn)保證只要有寫了日志的節(jié)點(diǎn)參與可恢復(fù):
1.只有上輪的eader有寫權(quán)限,并且zxid是自增的
2.tcp傳輸?shù)捻樞蛐院蛕k寫日志的順序性
日志被寫到過半節(jié)點(diǎn)
如果日志廣播到了過半節(jié)點(diǎn)并被寫入log歧强,那么這條數(shù)據(jù)肯定不會(huì)丟失澜薄,選舉需要過半節(jié)點(diǎn)參與,因此zxid最大的節(jié)點(diǎn)必然會(huì)包含這條日志摊册。在restore的過程中肤京,leader會(huì)將為提交的propasal再次廣播。