Hermes: a Fast, Fault-Tolerant and Linearizable Replication Protocol

提供高性能的讀寫服務(wù)是分布式研發(fā)工程師一直追求的目標(biāo),譬如在 TiDB 中诵原,我們就基于原生的一致性算法 Raft 做了非常多的改進(jìn)和性能優(yōu)化愤诱。當(dāng)然,在分布式領(lǐng)域丐膝,復(fù)制協(xié)議不光只有 Raft 這么一種量愧,譬如這段時(shí)間钾菊,我就看到了另一個(gè)不錯(cuò)的實(shí)現(xiàn),叫做 Hermes偎肃,來自于 Paper Hermes: a Fast, Fault-Tolerant and Linearizable Replication Protocol煞烫。

通常我們說分布式系統(tǒng)的高性能,無非就是關(guān)注兩點(diǎn):低延遲和高吞吐累颂,對(duì)于讀寫請(qǐng)求來說滞详,無非就是:

    • 能從所有副本讀取數(shù)據(jù)
    • 更少的網(wǎng)絡(luò)交互
    • 去中心化,不需要有單獨(dú)的地方進(jìn)行 serialization 處理
    • 完全并發(fā)紊馏,任何 replica 都能進(jìn)行寫入

對(duì)于 TiDB 來說料饥,雖然我們?cè)?Raft 這邊支持了 Follower Read,也就是能從任意副本讀取數(shù)據(jù)朱监,但在寫入上面岸啡,還是只有 Leader 能提供寫服務(wù)。但是 Hermes 卻能做到任何副本寫入赫编,所以讓我對(duì)這篇 Paper 非常有興趣巡蘸,讀下來之后,其實(shí)會(huì)發(fā)現(xiàn)沛慢,原來 Hermes 的原理非常的簡(jiǎn)單赡若。

在介紹原理之前,先階段的說下团甲,Hermes 使用的是非常通用的 logical timestamp 機(jī)制逾冬,后面用 LT 來表示,一個(gè) LT 是一個(gè) [V, Cid] 的 tuple躺苦,V 就是通常的 Lamport clock身腻,而 Cid 則是 replica 的 Node ID。如果對(duì)于一個(gè) Key 的并發(fā)寫入 V 是相同的匹厘,則按照 Cid 進(jìn)行排序嘀趟。

Hermes 的 replica 有 Coordinator 和 Follower 兩種,Coordinator 接受 client 的寫入請(qǐng)求愈诚,參考論文的圖她按,一次寫入如下:

  • Coordinator 接受 client 的 write 請(qǐng)求,將 Key 分配一個(gè)新的 LT炕柔,給其他 followers 也廣播一個(gè) Invalidation(INV) 消息酌泰。并且將 Key 變成 Write 狀態(tài)。
  • 其他 followers 收到 INV 之后匕累,會(huì)比較 LT陵刹,如果收到消息的 LT 比本地的大,就會(huì)將 Key 變成 Invalid 狀態(tài)(如果這個(gè) Key 之前是 Write 或者 Replay欢嘿,則會(huì)變成 Trans 狀態(tài))衰琐,并且回復(fù) ACK 消息也糊。無論之前比較的結(jié)果怎樣,ACK 里面的 LT 都是收到的 INV 的 LT羡宙。
  • 如果所有的 ACK 都收到了狸剃,write 就認(rèn)為完成,這個(gè) Key 就變成 Valid 狀態(tài)(如果之前處于 Trans 狀態(tài)辛辨,則會(huì)變成 Invalid 狀態(tài))
  • Coordinator 再次廣播 Validation(VAL) 消息
  • 當(dāng) Follower 收到 VAL 消息捕捂,只有 VAL 的 LT 等于之前本地的 local timestamp,才會(huì)將 Key 轉(zhuǎn)成 Valid 狀態(tài)斗搞,否則一律丟棄這個(gè) VAL 消息

可以看到,流程非常的簡(jiǎn)單慷妙,那么 Hermes 是如何支持 fault tolerance僻焚, Linearizability 這些特性的呢?

Hermes 保證膝擂,如果讀取的 Key 處于 Invalid 狀態(tài)虑啤,那么 read 則會(huì)一直等待,直到 Key 處于 Valid 狀態(tài)架馋。所以這里可以看到狞山,Hermes 采用 read wait 的方式滿足了 Linearizability。

而對(duì)于 fault tolerance叉寂,則是使用的 replayable write 的方式萍启,如果 Coordinator 在發(fā)送 VAL 消息之前跪了,那么就可能導(dǎo)致一個(gè) key 處于 invalid 狀態(tài)屏鳍。這里可以直接 replay write勘纯,因?yàn)?Hermes 會(huì)做如下事情:

  • INV 消息里面會(huì)帶上寫入的新值,這樣收到 INV 的 replica 都能知道這個(gè)值钓瞭,并且將其設(shè)置為 Invalid 狀態(tài)
  • Logical timestamp 能保證在每個(gè) replica 上面的 write 順序
  • 基于上述兩點(diǎn)驳遵,任何一個(gè)節(jié)點(diǎn)如果發(fā)現(xiàn)一個(gè) key 處于 Invalid 狀態(tài)超過一段時(shí)間,就可以認(rèn)為自己是 coordinator山涡,使用之前的 LT堤结,重新傳遞之前的 INV 消息,安全的 replay 這個(gè) write鸭丛。

Membership 變更

再來說說另一個(gè)需要關(guān)注的 membership 變更竞穷,Hermes 采用的是比較常用的做法,叫做 m-update系吩。一個(gè) m-update 包括:

  • 一個(gè)新的 lease
  • 一批新的 live nodes
  • 一個(gè)遞增的 epoch ID

一個(gè)接受了 m-update 的 replica 就可以當(dāng)成 coordinator 了来庭,這里需要注意:

  • 如果 read 處于 Valid 的 key,仍然是按照之前的方式處理
  • 如果 write 或者 read 處于 Invalid 的 key穿挨,則需要等 m-update 里面的 live nodes 接受到 m-update
  • 如果一個(gè) follower 還沒接受到 m-update月弛,則會(huì)丟棄后續(xù)的消息肴盏,因?yàn)檫@些消息的 epoch ID 會(huì)比 follower 當(dāng)前的 epoch ID 要大

Example

下面是 Paper 實(shí)際列舉的一個(gè)例子:

  1. Node 1 開始 write A = 1,同樣帽衙,node 3 開始 write A = 3菜皂。
  2. Node 2 收到 Node 1 的 INV 消息,回復(fù)了 ACK厉萝,并且將 Key A 變成了 Invalid 狀態(tài)
  3. Node 3 給 Node 1 也回復(fù)了 ACK恍飘,但 Node 3 并沒有改變 A 或者它的狀態(tài),因?yàn)?A 的 LT 是比 Node 1 發(fā)過來的 INV 要大的谴垫。
  4. Node 2 收到了 Node 3 的 INV章母,因?yàn)檫@個(gè) INV 的 LT 比之前的要大,所以 Node 2 更新了本地 A 的 LT 和 value
  5. Node 1 收到了 Node 3 的 INV翩剪,同理也更新了本地 A 的狀態(tài)
  6. Node 2 開始一次 read乳怎,因?yàn)?A 的狀態(tài)是 invalid,所以 read 會(huì) stalled前弯,然后收到 VAL 的消息蚪缀,就可以讀取了,這時(shí)候讀到的值是 3
  7. Node 1 收到了所有的 ACKs恕出,但仍然將 A 變成了 Invalid 狀態(tài)询枚,因?yàn)橹笆盏綇?Node 3 發(fā)來的帶有更大 LT 的 INV 消息,但還沒收到 Node 3 發(fā)來的 VAL 消息
  8. 如果 Node 3 跪掉了浙巫,Node 1 還沒收到 VAL 消息
    1. Lease 過期金蜀,Node 3 仍然是 failed,membership 更新
    2. 從 Node 1 讀取 A狈醉,會(huì)發(fā)現(xiàn)處于 Invalid 狀態(tài)廉油,Node 1 對(duì) A 進(jìn)行 replay 操作
    3. Node 2 收到消息不用處理,因?yàn)橛型瑯拥?LT
    4. Node 1 收到 Node 2 的 ACK苗傅,完成 replay抒线,并且廣播 VAL

寫在最后

上面只是簡(jiǎn)單的介紹了 Hermes 常用的讀寫流程以及成員變更方式,其實(shí) Hermes 還提供了 CAS 支持渣慕,不過我也懶得研究了嘶炭,總得來說,Hermes 還是非常簡(jiǎn)單的逊桦,而且非常容易實(shí)現(xiàn)眨猎,更難得可貴的是,Hermes 提供了 TLA+ 的證明强经,我現(xiàn)在也佩服我自己睡陪,竟然還能看得懂,之前的辛苦學(xué)習(xí)沒白費(fèi)。兰迫。信殊。

關(guān)于更多的信息,大家可以直接用官網(wǎng) https://hermes-protocol.com/ 看看汁果。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末涡拘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子据德,更是在濱河造成了極大的恐慌鳄乏,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件棘利,死亡現(xiàn)場(chǎng)離奇詭異橱野,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)赡译,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門仲吏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蝌焚,你說我怎么就攤上這事∈某猓” “怎么了只洒?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)劳坑。 經(jīng)常有香客問我毕谴,道長(zhǎng),這世上最難降的妖魔是什么距芬? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任涝开,我火速辦了婚禮,結(jié)果婚禮上框仔,老公的妹妹穿的比我還像新娘舀武。我一直安慰自己,他們只是感情好离斩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布银舱。 她就那樣靜靜地躺著,像睡著了一般跛梗。 火紅的嫁衣襯著肌膚如雪寻馏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天核偿,我揣著相機(jī)與錄音诚欠,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛轰绵,可吹牛的內(nèi)容都是我干的粉寞。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼藏澳,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼仁锯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起翔悠,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤业崖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后蓄愁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體双炕,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年撮抓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了妇斤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡丹拯,死狀恐怖站超,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情乖酬,我是刑警寧澤死相,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站咬像,受9級(jí)特大地震影響算撮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜县昂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一肮柜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧倒彰,春花似錦审洞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至耙箍,卻和暖如春撰糠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背辩昆。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國(guó)打工阅酪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓术辐,卻偏偏與公主長(zhǎng)得像砚尽,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子辉词,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353