自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

詳解 ZooKeeper 數(shù)據(jù)持久化

開(kāi)發(fā) 前端
們通過(guò)之前的文章有介紹過(guò),小S(Sync)負(fù)責(zé)對(duì)辦事處的數(shù)據(jù)進(jìn)行歸檔,所以今天他就是我們的主角,讓我們一起深入了解他的日常工作吧!

[[388266]]

本文轉(zhuǎn)載自微信公眾號(hào)「HelloGitHub」,作者HelloGitHub。轉(zhuǎn)載本文請(qǐng)聯(lián)系HelloGitHub公眾號(hào)。

Hi,這里是 HelloGitHub 推出的 HelloZooKeeper 系列,免費(fèi)開(kāi)源、有趣、入門(mén)級(jí)的 ZooKeeper 教程,面向有編程基礎(chǔ)的新手。

項(xiàng)目地址:https://github.com/HelloGitHub-Team/HelloZooKeeper

前一篇文章我們介紹了 ZK 是如何進(jìn)行選舉的,這篇我們開(kāi)始學(xué)習(xí) ZK 是如何將數(shù)據(jù)持久化到磁盤(pán)中的。

一、優(yōu)秀員工小S(Sync)

我們通過(guò)之前的文章有介紹過(guò),小S(Sync)負(fù)責(zé)對(duì)辦事處的數(shù)據(jù)進(jìn)行歸檔,所以今天他就是我們的主角,讓我們一起深入了解他的日常工作吧

為了喚醒大家的遠(yuǎn)古記憶,我放一張之前的

今天我們會(huì)重點(diǎn)講一下圖中的藍(lán)色部分,不過(guò)在此之前還是得先從整體架構(gòu)上介紹下 ZK 的數(shù)據(jù)管理,ZK 的數(shù)據(jù)大致是分為了兩部分,一個(gè)是內(nèi)存,一個(gè)就是磁盤(pán)文件。

1.1 內(nèi)存

雖然今天我們的主角是磁盤(pán)文件,但是內(nèi)存還是稍微再提一下下,幫助大家記憶的同時(shí)也能有一個(gè)比較全面的視角去認(rèn)知 ZK 整體的數(shù)據(jù)管理。

ZK 在內(nèi)存中的存儲(chǔ)就是之前故事中有提到的兩個(gè)賬本:小紅本和小黃本。如果排除作為回調(diào)通知記錄的小黃本,那 ZK 的內(nèi)存中就是小紅本對(duì)應(yīng)的哈希表而已,但是小黃本中的數(shù)據(jù)依然非常重要,所以需要將兩者作為整體一起看待,以及之前我有說(shuō)過(guò)小F(Final)掌管了這兩個(gè)賬本,作為業(yè)務(wù)處理的最后一個(gè)負(fù)責(zé)人,小S(Sync) 從時(shí)間上來(lái)說(shuō)是優(yōu)先于小F(Final)先處理的,所以 ZK 的設(shè)計(jì)是優(yōu)先將數(shù)據(jù)存入磁盤(pán),再去修改內(nèi)存中的數(shù)據(jù)保證盡可能的提升數(shù)據(jù)的可靠性。下面我們繼續(xù)了解磁盤(pán)文件(還真就提一下下!)

1.2 磁盤(pán)文件

ZK 的開(kāi)發(fā)者給 ZK 設(shè)計(jì)了兩種磁盤(pán)文件,對(duì)應(yīng)的路徑分別是 zoo.cfg 配置中的 dataDir 和 dataLogDir 這兩項(xiàng)目錄的配置。為了之后的描述清楚,我給這兩種磁盤(pán)文件起了名字:dataDir 對(duì)應(yīng) snapshot,dataLogDir 對(duì)應(yīng) log,log 就是的是小S(Sync)工作中的歸檔,snapshot 就是的是小S(Sync)工作中的快照。

log 是負(fù)責(zé)順序記錄每一個(gè)寫(xiě)請(qǐng)求到文件,snapshot 則是直接將整個(gè)內(nèi)存對(duì)象持久化至文件中。假設(shè)我現(xiàn)在 zoo.cfg 的配置是這樣:

  1. dataDir=/tmp/zookeeper/snapshot 
  2. dataLogDir=/tmp/zookeeper/log 

當(dāng) ZK 啟動(dòng)后會(huì)基于上面兩個(gè)路徑繼續(xù)創(chuàng)建 version-2 子路徑,之后的文件都會(huì)在該子路徑下創(chuàng)建

  1. /tmp 
  2. └── zookeeper 
  3.     ├── snapshot 
  4.       └── version-2 
  5.         └── ... 
  6.     └── log 
  7.       └── version-2 
  8.         └── ... 

二、文件的創(chuàng)建和寫(xiě)入

兩種文件分別是在什么時(shí)候被寫(xiě)入磁盤(pán)的呢?寫(xiě)入的內(nèi)容又是哪些呢?我們接下來(lái)對(duì)兩種文件一一進(jìn)行分析。

2.1 log 文件

log 文件名的格式是這樣 log.{zxid} zxid 對(duì)應(yīng)當(dāng)時(shí)創(chuàng)建該文件時(shí)的最大 zxid,假設(shè)現(xiàn)在創(chuàng)建時(shí) zxid 為 0,那目錄結(jié)構(gòu)會(huì)是這樣:

  1. /tmp 
  2. └── zookeeper 
  3.     └── log 
  4.       └── version-2 
  5.         └── log.0 

這個(gè) log.0 文件創(chuàng)建的時(shí)機(jī)你也可以簡(jiǎn)單的理解為當(dāng)服務(wù)端收到第一個(gè)寫(xiě)請(qǐng)求的時(shí)候,而且當(dāng)創(chuàng)建完成后,并不能直接將數(shù)據(jù)寫(xiě)入,而是要先寫(xiě)一些文件頭的字段,比如大名鼎鼎的魔數(shù),版本號(hào)等元信息。

而 log 文件的魔數(shù)是 ZKLG(4 個(gè)字節(jié)),版本號(hào)固定為 2(4 個(gè)字節(jié)),還要記錄一個(gè) dbId 固定為 0(8 個(gè)字節(jié)) (當(dāng)前沒(méi)用,可能之后會(huì)派用處吧),所以前 16 個(gè)字節(jié)是固定這樣的:

  1. Z K L G        2                 0 
  2. A4B4C47 00000002 00000000 00000000 

那之后的業(yè)務(wù)數(shù)據(jù)是如何記錄的呢?

每一個(gè)寫(xiě)請(qǐng)求都可以分為四個(gè)部分:校驗(yàn)和、請(qǐng)求頭、請(qǐng)求數(shù)據(jù)、簽名,校驗(yàn)和是通過(guò)后面三個(gè)字段計(jì)算出來(lái)的,小S每次收到寫(xiě)請(qǐng)求后都會(huì)按照這樣的順序?qū)?duì)應(yīng)請(qǐng)求的四個(gè)字段寫(xiě)入 log 文件,由于不同的業(yè)務(wù)請(qǐng)求數(shù)據(jù)不固定,而且數(shù)據(jù)長(zhǎng)度也比較大,這里就不給大家展示具體的值(如果大家想要知道這硬核的存儲(chǔ)過(guò)程,不妨給我留言,我以后單獨(dú)做下,嘗試逐個(gè)字節(jié)解釋)

然后是 zookeeper.txnLogSizeLimitInKb 這個(gè)環(huán)境變量配置,默認(rèn)是 -1,這個(gè)配置限制了 log 單個(gè)文件大小(單位是 KB),每次小S(Sync)歸檔的時(shí)候(圖中右下角粉色部分“是否歸檔”),將數(shù)據(jù)統(tǒng)一刷到磁盤(pán)后,如果用戶(hù)手動(dòng)配置了該參數(shù),就會(huì)檢查當(dāng)前 log 文件大小是否超過(guò)了該參數(shù)大小,如果超過(guò)了就會(huì)進(jìn)行 rollLog,相當(dāng)于下一次的寫(xiě)請(qǐng)求會(huì)創(chuàng)建一個(gè)新的 log 文件。除此之外,當(dāng)小S(Sync)每次快照的時(shí)候會(huì)強(qiáng)制執(zhí)行一次 rollLog。

2.2 snapshot 文件

snapshot 文件名的格式是這樣 snapshot.{zxid} zxid 對(duì)應(yīng)當(dāng)是創(chuàng)建該文件時(shí)的最大 zxid,假設(shè)現(xiàn)在創(chuàng)建是最大 zxid 是 0,那目錄結(jié)構(gòu)會(huì)是這樣:

  1. /tmp 
  2. └── zookeeper 
  3.     └── snapshot 
  4.       └── version-2 
  5.         └── snapshot.0 

而關(guān)于是否快照(圖中中間區(qū)域粉色部分“是否快照”),之前有簡(jiǎn)單介紹過(guò)是和隨機(jī)數(shù)有關(guān),這次我們深入了解下。

首先有兩個(gè)配置 zookeeper.snapCount (默認(rèn) 100000)和 zookeeper.snapSizeLimitInKb(默認(rèn) 4194304 單位是KB,相當(dāng)于 4 GB)在啟動(dòng)后會(huì)基于這兩個(gè)配置分別生成兩個(gè)隨機(jī)數(shù),假設(shè)上述的配置是按照默認(rèn)的設(shè)置,這兩個(gè)隨機(jī)數(shù)的范圍就是:

  1. randRoll = [0, 50000] 
  2. randSize = [0, 4194304 * 1024 / 2] 

可以簡(jiǎn)單的認(rèn)為就是上述兩個(gè)配置的一半之內(nèi)的隨機(jī)數(shù),至于 randSize 為什么要乘以 1024 因?yàn)樽罱K文件計(jì)算大小是以 byte 作為單位的。

而是否快照就是取決于上面兩個(gè)隨機(jī)數(shù),有兩個(gè)條件:

  • 當(dāng)前寫(xiě)請(qǐng)求的數(shù)量達(dá)到了 zookeeper.snapCount 的一半并加上 randRoll 的數(shù)量
  • 當(dāng)前 log 文件的大小達(dá)到了 zookeeper.snapSizeLimitInKb 的一半并加上 randSize 的大小

上述條件滿(mǎn)足任意一個(gè)條件后就會(huì)重置上面的兩個(gè)隨機(jī)數(shù),并開(kāi)始生成快照,生成快照這個(gè)過(guò)程是啟動(dòng)一個(gè)子線(xiàn)程去創(chuàng)建的。

snapshot 和 log 還有個(gè)不同的地方就是,snapshot 文件 ZK 提供了三種不同的壓縮實(shí)現(xiàn),GZIP、SNAPPY、CHECKED,通過(guò) zookeeper.snapshot.compression.method 進(jìn)行配置,默認(rèn)是 CHECKED,就是原始按照字節(jié)順序?qū)懭?,另外兩個(gè)這里就不展開(kāi)了。那我們接下來(lái)看看 snapshot 文件是怎么記的吧。

和 log 文件一樣,也要先記一些文件的頭部字段,而 snapshot 文件的魔數(shù)是 ZKSN(4 個(gè)字節(jié)),版本號(hào)固定為 2(4 個(gè)字節(jié)),還要記錄一個(gè) dbId 固定為 -1(8 個(gè)字節(jié)) (當(dāng)前沒(méi)用,可能之后會(huì)派用處吧),所以前 16 個(gè)字節(jié)是固定這樣的:

  1. Z K S N        2         -1 
  2. 5A4B534E 00000002 FFFFFFFF FFFFFFFF 

然后緊跟其后的部分客戶(hù)端的會(huì)話(huà)信息,客戶(hù)端的數(shù)量,然后循環(huán)記錄每一個(gè)客戶(hù)端的 sessionId、超時(shí)時(shí)間,然后是小紅本里的所有信息了包括但不限于 ACL,節(jié)點(diǎn)的統(tǒng)計(jì)數(shù)據(jù),節(jié)點(diǎn)的數(shù)據(jù),子節(jié)點(diǎn)的信息等。最后一部分就是校驗(yàn)和和簽名。和 log 一樣,如果大家有興趣的話(huà),我之后單獨(dú)再做一篇逐個(gè)字節(jié)講解的。

三、從文件中恢復(fù)

如果只是單單存文件,那這文件也沒(méi)什么用,所以文件另一個(gè)重要用途就是幫助 ZK 恢復(fù)服務(wù)端的信息。

在 ZK 啟動(dòng)的時(shí)候就會(huì)嘗試讀取 dataDir 和 dataLogDir 這兩個(gè)目錄下的文件,假設(shè)在這兩個(gè)路徑下的文件是:

  1. /tmp 
  2. └── zookeeper 
  3.     ├── snapshot 
  4.       └── version-2 
  5.         └── snapshot.5 
  6.         └── snapshot.37 
  7.         └── snapshot.100 
  8.     └── log 
  9.       └── version-2 
  10.         └── log.0 
  11.         └── log.6 
  12.         └── log.38 
  13.         └── log.90 
  14.         └── log.108 

我這里例子中的文件名的后綴數(shù)字是我隨便舉例只是為了說(shuō)明恢復(fù)的過(guò)程,實(shí)際未必是這樣,切記。

現(xiàn)在 ZK 服務(wù)端啟動(dòng)后,會(huì)先從 snapshot 的目錄中找到 zxid 最大的那個(gè)文件,然后根據(jù)它的內(nèi)容恢復(fù)小紅本

恢復(fù)完后就會(huì)去 log 文件目錄下尋找所有比 100 要大的 log 文件以及比 100 要略小一點(diǎn)的 log 文件,本例子中就是 log.90 和 log.108 這兩個(gè)文件。

你可能會(huì)問(wèn)為什么要找小于 100 的 log.90 這個(gè)文件呢?因?yàn)槲募械?90 只是說(shuō)明這個(gè)文件建立的時(shí)候,最大的 zxid 是 90,但是文件中記錄的寫(xiě)請(qǐng)求是很有可能會(huì)大于 100 的,所以 log.90 也需要被找到。

然后就是從 log.90 這個(gè)文件開(kāi)始恢復(fù),先從 zxid 比 100 大的寫(xiě)請(qǐng)求開(kāi)始讀取并執(zhí)行該寫(xiě)請(qǐng)求,然后繼續(xù)讀取 log.108,等待所有符合條件的 log 文件讀取后,整個(gè) ZK 的數(shù)據(jù)就恢復(fù)完成了。

四、總結(jié)

今天我們介紹了關(guān)于 ZK 持久化的知識(shí):

ZK 會(huì)持久化到磁盤(pán)的文件有兩種:log 和 snapshot

log 負(fù)責(zé)記錄每一個(gè)寫(xiě)請(qǐng)求

snapshot 負(fù)責(zé)對(duì)當(dāng)前整個(gè)內(nèi)存數(shù)據(jù)進(jìn)行快照

恢復(fù)數(shù)據(jù)的時(shí)候,會(huì)先讀取最新的 snapshot 文件

然后在根據(jù) snapshot 最大的 zxid 去搜索符合條件的 log 文件,再通過(guò)逐條讀取寫(xiě)請(qǐng)求來(lái)恢復(fù)剩余的數(shù)據(jù)

今天的內(nèi)容還是比較簡(jiǎn)單的,為我們下一篇文章打好了基礎(chǔ)~下一篇我們開(kāi)始介紹之前選舉中沒(méi)有介紹的內(nèi)容:選舉完成后,F(xiàn)ollower 和 Observer 是如何同 Leader 同步數(shù)據(jù)的?

 

責(zé)任編輯:武曉燕 來(lái)源: HelloGitHub
相關(guān)推薦

2011-08-17 15:19:38

iPhone應(yīng)用數(shù)據(jù)

2019-05-15 09:04:47

Redis數(shù)據(jù)存儲(chǔ)數(shù)據(jù)

2019-05-15 09:44:33

數(shù)據(jù)Redis持久化

2024-09-29 09:25:53

2023-12-14 07:30:04

PicklePython模塊

2011-08-25 14:26:40

LUA數(shù)據(jù)文件

2023-08-17 16:17:00

Docker前端

2024-04-03 15:40:14

WebSocketWeb應(yīng)用Spring

2019-05-17 08:55:49

RedisRDBAOF

2024-09-06 17:49:46

2011-07-07 15:45:45

iPhone SQLite 數(shù)據(jù)

2024-04-25 16:17:53

SentinelNacos數(shù)據(jù)源

2013-09-12 14:56:02

iOS持久化

2018-12-14 09:48:23

Redis數(shù)據(jù)故障

2020-01-06 14:54:31

RDBAOFRedis

2011-06-07 17:16:47

iPhone 數(shù)據(jù)

2022-08-30 10:15:27

Kubernetes數(shù)據(jù)持久化管理

2017-09-21 08:16:33

數(shù)據(jù)存儲(chǔ)環(huán)境

2024-03-26 00:03:08

Redis數(shù)據(jù)RDB

2023-11-26 09:06:46

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)