91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

wal怎么實現日志讀寫

發布時間:2021-12-18 15:36:08 來源:億速云 閱讀:257 作者:iii 欄目:云計算

這篇文章主要介紹“wal怎么實現日志讀寫”,在日常操作中,相信很多人在wal怎么實現日志讀寫問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”wal怎么實現日志讀寫”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

etcd raft介紹

etcd raft是目前使用最廣泛的raft庫, etcd raft在etcd, Kubernetes, Docker Swarm, Cloud Foundry Diego, CockroachDB, TiDB, Project Calico, Flannel等分布式系統中都有應用,在生成環境得到了驗證。 傳統raft庫的實現都是單體設計(集成了存儲層、消息序列化、網絡層等), etcd raft繼承了簡約的設計理念,只實現了最核心的raft算法, 這樣更加的靈活。etcd將網絡、日志存儲、快照等功能分開,通過獨立的模塊實現,用戶可以在需要時調用。etcd自身實現了自己的一套raft配套庫:etcd-wal(用于存儲日志),snap(用于存儲快照),MemoryStorage(用于存儲當前日志、快照、狀態等信息以供raft核心程序使用)。

wal怎么實現日志讀寫

etcd wal介紹

WAL是write ahead log的縮寫,etcd使用wal模塊來完成raft日志的持久化存儲,etcd對wal的所有實現都放在wal目錄中。

wal數據結構

type WAL struct {
lg *zap.Logger

dir string // the living directory of the underlay files

// dirFile is a fd for the wal directory for syncing on Rename
dirFile *os.File

metadata []byte // metadata recorded at the head of each WAL
state raftpb.HardState // hardstate recorded at the head of WAL

start walpb.Snapshot // snapshot to start reading
decoder *decoder // decoder to decode records
readClose func() error // closer for decode reader

mu sync.Mutex
enti uint64 // index of the last entry saved to the wal
encoder *encoder // encoder to encode records

locks []*fileutil.LockedFile // the locked files the WAL holds (the name is increasing)
fp *filePipeline
}

上述為wal的數據結構,通過用wal.go文件中的Create()方法來獲取wal的實例。wal首先會創建一個臨時目錄并初始化相關變量,并創建和初始化第一個wal文件,等所有的操作都初始化完成后直接更改臨時目錄的名字完成wal實例的初始化。

文件組織

wal的所有日志放在一個指定目錄下,日志的文件名以 .wal 作為結尾,格式為-.wal,seq和index的格式都為%016x,例如:0000000000000001-0000000000000001.wal。index代表這個文件中第一條raft日志的index,seq是這個文件的序列號(依次遞增)。

每個文件的大小默認為64M,當文件大于64M時,wal會自動生成新的日志文件用于存儲日志。每個日志文件都會使用flock鎖定文件,參數為LOCK_EX,這是一把獨有鎖,同一時間只能有一個進程可以操作這個日志文件,所以當wal占有這個文件時,通過進程是無法刪除這個文件的。

日志邏輯組織

wal日志可以存儲多種類型的數據,具體如下。

wal怎么實現日志讀寫

wal怎么實現日志讀寫

  • crcType 每個新的日志文件的第一條記錄都會是crcType類型的記錄,crcType也只會在每個日志文件的開始時寫入,用于記錄上一個文件最后的crc是多少

  • metadataType 每個新的日志文件中metadataType緊跟在crcType記錄后面,每個日志文件只會出現一次

  • stateType 這種日志類型會在兩種情況下加入:

  1. 自動切分日志文件時,新的日志文件中,緊跟在metadataType后面會存入一條stateType的日志

  2. 當raft核心程序ready中返回hard state時也會存儲該類型的日志

  • snapshotType wal日志中只會存儲snapshot的term和index,具體的數據存儲在專門的snapshot中,每次存儲快照都會在wal日志中存儲一個wal的快照。當存儲快照時,會將快照之前index的日志文件都釋放掉。wal中存儲的snapshot主要用于檢查快照是否正確。

日志讀寫

wal通過封裝的encoder和decoder模塊來實現日志讀寫。

寫日志

encoder模塊把會增量的計算crc和數據一起寫入到wal文件中。 下面為encoder數據結構

type encoder struct {
mu sync.Mutex
bw *ioutil.PageWriter

crc hash.Hash42
buf []byte //緩存空間,默認為1M,降低數據分配的壓力
uint64buf []byte
}

wal通過encoder實現寫日志,在這個模塊中會完成crc的計算。wal為了更好的管理數據,日志中的每條數據都會以8字節對齊(wal會自動對齊字節)。 日志寫入的流程如下。

wal怎么實現日志讀寫

圖中的crc是增量計算,以之前的所有日志數據為增量基礎。 wal只關注寫入日志,不會校驗日志的index是否重復,但是如果重啟這個Node的話,系統會自動過濾掉中間混雜的日志。

日志切分

wal實現了日志自動切分,當日志數據大于默認的64M時就會生成新的文件寫入日志,日志的切分通過wal.go文件中的cut方法來實現。cut方法只會在調用wal中的Save方法才會觸發調用,新文件的第一條記錄就是上一個wal文件最后的crc。

日志compact

wal沒有實現日志的自動compact,系統只提供了MemoryStorage的日志compact方法(需要用戶主動調用)。

file_pipeline模塊

wal新建新的文件時都是先新建一個tmp文件,當所有操作都完成后再重命名這個文件。wal使用file_pipeline這個模塊在后臺啟動一個協程時刻準備一個臨時文件以供使用,從而避免臨時創建文件的開銷。

etcd snap介紹

etcd raft自帶了go.etcd.io/etcd/etcdserver/api/snap模塊來實現快照的存儲。

文件組織

在snap模塊中一個快照用一個后綴名為.snap的文件存儲,文件格式為-.snap, term和index分別代表快照日志所處的term和index。 每個快照具體存儲結構如下圖:

wal怎么實現日志讀寫

詳細介紹

系統可以有多個快照,snap模塊使用Snapshotter結構統一管理快照。

type Snapshotter struct {
lg *zap.Logger
dir string
}

上面snapshotter的結構代碼,snapshotter主要用于存儲和讀取快照。

快照具體存儲的內容需要用戶來指定,例如在raft的官方例子中直接將當時的kv數據Marshal之后存儲到快照中。

func (s *kvstore) getSnapshot() ([]byte, error) {
s.mu.RLock()
defer s.mu.RUnlock()
return json.Marshal(s.kvStore)
}

何時打快照

在etcd-raft中用戶可以選擇何時打快照,在etcd的官方案例中打快照的方法是maybeTriggerSnapshot(),這個方法在節點的Ready()方法返回時調用,當前提交的index值與上一次大快照的index值大于10000時會打新的快照。

etcd MemoryStorage介紹

MemoryStorage用于存儲raft節點臨時的數據,包括entrys、快照等。用戶將數據存儲到memoryStorage中,raft節點也會使用這些數據。包括entrys的傳遞、快照的發送等都是從memoryStorage中發送。

// MemoryStorage implements the Storage interface backed by an
// in-memory array.
type MemoryStorage struct {
// Protects access to all fields. Most methods of MemoryStorage are
// run on the raft goroutine, but Append() is run on an application
// goroutine.
sync.Mutex

hardState pb.HardState
snapshot pb.Snapshot
// ents[i] has raft log position i+snapshot.Metadata.Index
ents []pb.Entry
}

memoryStorage會存儲最新的entrys(包括哪些沒有commit)、快照和狀態,用戶在收到其它節點發送的相關數據時需要將數據存儲到memorystorage中。

    到此,關于“wal怎么實現日志讀寫”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    wal
    AI

    郎溪县| 芦山县| 澄城县| 盱眙县| 遂溪县| 桦甸市| 泾阳县| 德庆县| 游戏| 齐河县| 林芝县| 增城市| 军事| 白山市| 南阳市| 渝北区| 拜城县| 黑山县| 内黄县| 双牌县| 曲阜市| 雅安市| 临桂县| 安岳县| 临湘市| 台前县| 读书| 金阳县| 淮南市| 正蓝旗| 正定县| 陕西省| 石城县| 江阴市| 美姑县| 泗洪县| 景泰县| 牡丹江市| 新竹市| 太湖县| 沾益县|