ETCD核心機制解析

2021-10-10 09:03:17 字數 4645 閱讀 8819

etcd整體機制

etcd 是乙個分布式的、可靠的 key-value 儲存系統,它適用於儲存分布式系統中的關鍵資料。

etcd 集群中多個節點之間通過raft演算法完成分布式一致性協同,演算法會選舉出乙個主節點作為 leader,由 leader 負責資料的同步與分發。當 leader 出現故障後系統會自動地重新選取另乙個節點成為 leader,並重新完成資料的同步。

etcd集群實現高可用主要是基於quorum機制,即:集群中半數以上的節點可用時,集群才可繼續提供服務,quorum機制在分布式一致性演算法中應用非常廣泛,此處不再詳細闡述。

raft資料更新和etcd呼叫是基於兩階段機制:

第一階段 leader記錄log (uncommited);日誌複製到follower;follower響應,操作成功,響應客戶端;呼叫者呼叫leader,leader會將kv資料儲存在日誌中,並利用實時演算法raft進行複製

第二階段 leader commit;通知follower;當複製給了n+1個節點後,本地提交,返回給客戶端,最後leader非同步通知follower完成通知

etcd核心api分析

type kv inte***ce ).

put(ctx context.context, key, val string, opts ...opoption) (*putresponse, error)

// get retrieves keys.

// by default, get will return the value for "key", if any.

// when passed withrange(end), get will return the keys in the range [key, end).

// when passed withfromkey(), get returns keys greater than or equal to key.

// when passed withrev(rev) with rev > 0, get retrieves keys at the given revision;

// if the required revision is compacted, the request will fail with errcompacted .

// when passed withlimit(limit), the number of returned keys is bounded by limit.

// when passed withsort(), the keys will be sorted.

get(ctx context.context, key string, opts ...opoption) (*getresponse, error)

// delete deletes a key, or optionally using withrange(end), [key, end).

delete(ctx context.context, key string, opts ...opoption) (*deleteresponse, error)

// compact compacts etcd kv history before the given rev.

compact(ctx context.context, rev int64, opts ...compactoption) (*compactresponse, error)

// txn creates a transaction.

txn(ctx context.context) txn

}

主要有put、get、delete、compact、do和txn方法;put用於向etcd集群中寫入訊息,以key value的形式儲存;get可以根據key檢視其對應儲存在etcd中的資料;delete通過刪除key來刪除etcd中的資料;compact 方法用於壓縮 etcd 鍵值對儲存中的事件歷史,避免事件歷史無限制的持續增長;txn 方法在單個事務中處理多個請求,etcd事務模式為:

if compare

then op

else op

commit

type lease inte***ce

lease 是分布式系統中乙個常見的概念,用於代表乙個分布式租約。典型情況下,在分布式系統中需要去檢測乙個節點是否存活的時,就需要租約機制。

grant方法用於建立乙個租約,當伺服器在給定 time to live 時間內沒有接收到 keepalive 時租約過期;revoke撤銷乙個租約,所有附加到租約的key將過期並被刪除;timetolive 獲取租約資訊;keepalive 通過從客戶端到伺服器端的流化的 keep alive 請求和從伺服器端到客戶端的流化的 keep alive 應答來維持租約;檢測分布式系統中乙個程序是否存活,可以在程序中去建立乙個租約,並在該程序中週期性的呼叫 keepalive 的方法。如果一切正常,該節點的租約會一致保持,如果這個程序掛掉了,最終這個租約就會自動過期,在 etcd 中,允許將多個 key 關聯在同乙個 lease 之上,可以大幅減少 lease 物件重新整理帶來的開銷。

type watcher inte***ce

etcd 的watch 機制可以實時地訂閱到 etcd 中增量的資料更新,watch 支援指定單個 key,也可以指定乙個 key 的字首。watch 觀察將要發生或者已經發生的事件,輸入和輸出都是流;輸入流用於建立和取消觀察,輸出流傳送事件。

乙個觀察 rpc 可以在一次性在多個key範圍上觀察,並為多個觀察流化事件,

整個事件歷史可以從最後壓縮修訂版本開始觀察。

etcd資料版本機制

etcd資料版本中主要有term表示leader的任期,

revision 代表的是全域性資料的版本。當集**生 leader 切換,term 的值就會 +1,在節點故障,或者 leader 節點網路出現問題,再或者是將整個集群停止後再次拉起,都會發生 leader 的切換;當資料發生變更,包括建立、修改、刪除,其 revision 對應的都會 +1,在集群中跨 leader 任期之間,revision 都會保持全域性單調遞增,集群中任意一次的修改都對應著乙個唯一的 revision,因此我們可以通過 revision 來支援資料的 mvcc,也可以支援資料的 watch。

對於每乙個 keyvalue 資料節點,etcd 中都記錄了三個版本:

在同乙個 leader 任期之內,所有的修改操作,其對應的 term 值始終相等,而 revision 則保持單調遞增。當重啟集群之後,所有的修改操作對應的 term 值都加1了。

etcd之mvcc併發控制

說起mvcc大家都不陌生,mysql的innodb中

就使用mvcc實現高併發的資料訪問,對資料進行多版本處理,並通過事務的可見性來保證事務能看到自己應該看到的資料版本,同樣,在etcd中也使用mvcc進行併發控制。

etcd支援對同乙個 key 發起多次資料修改,每次資料修改都對應乙個版本號。etcd記錄了每一次修改對應的資料,即乙個 key 在 etcd 中存在多個歷史版本。在查詢資料的時候如果不指定版本號,etcd 會返回 key 對應的最新版本,同時etcd 也支援指定乙個版本號來查詢歷史資料。

etcd將每一次修改都記錄下來,使用 watch訂閱資料時,可以支援從任意歷史時刻(指定 revision)開始建立乙個 watcher,在客戶端與 etcd 之間建立乙個資料管道,etcd 會推送從指定 revision 開始的所有資料變更。etcd 提供的 watch 機制保證,該 key 的資料後續的被修改之後,通過這個資料管道即時的推送給客戶端。

分析其原始碼可知:

type revision struct 

func (a revision) greaterthan(b revision) bool

if a.main < b.main

return a.sub > b.sub

}

在etcd的mvcc實現中有乙個revision結構體,main 表示當前操作的事務 id,全域性自增的邏輯時間戳,sub 表示當前操作在事務內部的子 id,事務內自增,從 0 開始;通過greaterthan方法進行事務版本的比較。

etcd儲存資料結構

etcd 中所有的資料都儲存在乙個 btree的資料結構中,該btree儲存在磁碟中,並通過mmap的方式對映到記憶體用來支援快速的訪問,treeindex的定義如下:

type treeindex struct 

func newtreeindex() index

}

index所繫結對btree的操作有put、get、revision、range及visit等,以put方法為例,其原始碼如下:

func (ti *treeindex) put(key byte, rev revision) 

ti.lock()

defer ti.unlock()

item := ti.tree.get(keyi)

if item == nil

okeyi := item.(*keyindex)

okeyi.put(rev.main, rev.sub)

}

通過原始碼可知對btree資料的讀寫操作都是在加鎖下完成的,從而來保證併發下資料的一致性。

platform核心機制

platform 核心機制 guolele 2011.1.21 platform 是2.6 核心新引進的虛擬匯流排,而且現在有很多裝置驅動都是掛載在虛擬匯流排上,特別是幀緩衝裝置都是建立在平台匯流排基礎上,這也使得 lcd等圖形驅動也不可避免的使用平台匯流排,下面簡單分析一下平台匯流排的機制。首先先...

Flask核心機制 current app

flask的request物件是乙個全域性物件,跟django的request不太一樣,django的request物件是每次請求乙個,但是flask全域性就乙個request物件,但是每次請求它能區分開是哪個請求,這個做的挺牛逼的,我去看了一下它的原始碼,原來是寫了乙個local類,來處理不同執行...

Kafka核心概念及核心機制

broker 程序 producer 生產者 flume consumer 消費者 ss spark streaming,topic 主題 分割槽 副本數 資料夾 partition 分割槽乙個分割槽可以有多個副本 重點解析 1.乙個組內,共享乙個公共的groupid 2.組內的所有消費者協調一起,...