偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

淺談分布式一致性:Raft 與 SOFAJRaft

開發(fā) 開發(fā)工具 分布式
對(duì)于一個(gè)無限增長(zhǎng)的序列a[1, 2, 3…],如果對(duì)于任意整數(shù)i, a[i]的值滿足分布式一致性, 這個(gè)系統(tǒng)就滿足一致性狀態(tài)機(jī)的要求。

[[403519]]

 一 分布式共識(shí)算法 (Consensus Algorithm)

1 如何理解分布式共識(shí)?

多個(gè)參與者針對(duì)某一件事達(dá)成完全一致:一件事,一個(gè)結(jié)論。

已達(dá)成一致的結(jié)論,不可推翻。

2 有哪些分布式共識(shí)算法?

  • Paxos:被認(rèn)為是分布式共識(shí)算法的根本,其他都是其變種,但是 paxos 論文中只給出了單個(gè)提案的過程,并沒有給出復(fù)制狀態(tài)機(jī)中需要的 multi-paxos 的相關(guān)細(xì)節(jié)的描述,實(shí)現(xiàn) paxos 具有很高的工程復(fù)雜度(如多點(diǎn)可寫,允許日志空洞等)。
  • Zab:被應(yīng)用在 zookeeper 中,業(yè)界使用廣泛,但沒用抽象成通用 library。
  • Raft:以容易理解著稱,業(yè)界也涌現(xiàn)出很多 raft 實(shí)現(xiàn),比如 etcd、braft、tikv 等。

二 Raft 介紹

1 特點(diǎn):Strong Leader

  • 系統(tǒng)中必須存在且同一時(shí)刻只能有一個(gè) leader,只有 leader 可以接受 clients 發(fā)過來的請(qǐng)求。
  • Leader 負(fù)責(zé)主動(dòng)與所有 followers 通信,負(fù)責(zé)將“提案”發(fā)送給所有followers,同時(shí)收集多數(shù)派的 followers 應(yīng)答。
  • Leader 還需向所有 followers 主動(dòng)發(fā)送心跳維持領(lǐng)導(dǎo)地位(保持存在感)。

另外,身為 leader 必須保持一直 heartbeat 的狀態(tài)。

2 復(fù)制狀態(tài)機(jī)

對(duì)于一個(gè)無限增長(zhǎng)的序列a[1, 2, 3…],如果對(duì)于任意整數(shù)i, a[i]的值滿足分布式一致性, 這個(gè)系統(tǒng)就滿足一致性狀態(tài)機(jī)的要求。

基本上所有的真實(shí)系統(tǒng)都會(huì)有源源不斷的操作,這時(shí)候單獨(dú)對(duì)某個(gè)特定的值達(dá)成一致顯然是不夠的。為了讓真實(shí)系統(tǒng)保證所有的副本的一致性,通常會(huì)把操作轉(zhuǎn)化為 write-ahead-log(WAL)。然后讓系統(tǒng)中所有副本對(duì) WAL 保持一致,這樣每個(gè)副本按照順序執(zhí)行 WAL 里的操作,就能保證最終的狀態(tài)是一致的。

  • Client 向 leader 發(fā)送寫請(qǐng)求。
  • Leader 把“操作”轉(zhuǎn)化為 WAL 寫本地 log 的同時(shí)也將 log 復(fù)制到所有 followers。
  • Leader 收到多數(shù)派應(yīng)答,將 log 對(duì)應(yīng)的“操作”應(yīng)用到狀態(tài)機(jī)。
  • 回復(fù) client 處理結(jié)果。

3 Raft 中的基本概念

Raft-node 的 3 種角色/狀態(tài)

  • Follower:完全被動(dòng),不能發(fā)送任何請(qǐng)求, 只接受并響應(yīng)來自 leader 和 candidate 的 message, node啟動(dòng)后的初始狀態(tài)必須是 follower。
  • Leader:處理所有來自客戶端的請(qǐng)求,以及復(fù)制 log 到所有 followers。
  • Candidate:用來競(jìng)選一個(gè)新 leader (candidate 由 follower 觸發(fā)超時(shí)而來)。

Message 的 3 種類型

  • RequestVote RPC:Candidate 發(fā)出。
  • AppendEntries (Heartbeat) RPC:Leader 發(fā)出。
  • InstallSnapshot RPC:Leader 發(fā)出。

任期邏輯時(shí)鐘

  • 時(shí)間被劃分為一個(gè)個(gè)任期(term),term id 按時(shí)間軸單調(diào)遞增。
  • 每一個(gè)任期的開始都是 leader 選舉,選舉成功之后,leader在任期內(nèi)管理整個(gè)集群, 也就是“選舉 + 常規(guī)操作”。
  • 每個(gè)任期最多一個(gè) leader,可以沒有 leader (spilt-vote 導(dǎo)致)。

4 Raft 功能分解

Leader 選舉

超時(shí)驅(qū)動(dòng):Heartbeat / Election timeout

隨機(jī)的超時(shí)時(shí)間:降低選舉碰撞導(dǎo)致選票被瓜分的概率

選舉流程:Follower --> Candidate (選舉超時(shí)觸發(fā))

  • 贏得選舉:Candidate --> Leader
  • 另一個(gè)節(jié)點(diǎn)贏得選舉:Candidate --> Follower
  • 一段時(shí)間內(nèi)沒有任何節(jié)點(diǎn)器贏得選舉:Candidate --> Candidate

選舉動(dòng)作:

  • Current term++
  • 發(fā)送 RequestVote RPC

New Leader 選取原則 (最大提交原則):

  • Candidates include log info in RequestVote RPCs(index & term of last log entry)
  • During elections, choose candidate with log most likely to contain all committed entries
  • Voting server V denies vote if its log is “more complete”:(lastTermV > lastTermC) ||((lastTermV == lastTermC) && (lastIndexV > lastIndexC))
  • Leader will have “most complete” log among electing majority

安全性:一個(gè) term,最多選出一個(gè) leader,可以沒 leader,下一個(gè) term 再選。

影響 raft 選舉成功率的幾個(gè)時(shí)間參數(shù):

  • RTT(Round Trip Time):網(wǎng)絡(luò)延時(shí)
  • Heartbeat timeout:心跳間隔,通常應(yīng)該比 election timeout 小一個(gè)數(shù)量級(jí),目的是讓 leader 能夠持續(xù)發(fā)送心跳來阻止 followers 觸發(fā)選舉
  • Election timeout:Leader 與 followers 間通信超時(shí)觸發(fā)選舉的時(shí)間
  • MTBF(Meantime Between Failure):Servers 連續(xù)常規(guī)故障時(shí)間間隔 RTT << Heartbeat timeout < Election timeout(ET) << MTBF

隨機(jī)選主觸發(fā)時(shí)間:Random(ET, 2ET)

日志復(fù)制

Raft 日志格式:

  • (TermId, LogIndex, LogValue)
  • 其中 (TermId, LogIndex) 能確定唯一一條日志

Log replication關(guān)鍵點(diǎn):

  • 連續(xù)性:日志不允許出現(xiàn)空洞
  • 有效性:
    • 不同節(jié)點(diǎn),擁有相同 term 和 logIndex 的日志 value 一定相同
    • Leader 上的日志一定是有效的
    • Follower 上的日志是否有效,通過 leader 日志對(duì)比判斷 (How?)

Followers 日志有效性檢查:

  • AppendEntries RPC 中還會(huì)攜帶前一條日志的唯一標(biāo)識(shí) (prevTermId, prevLogIndex)
  • 遞歸推導(dǎo)

Followers 日志恢復(fù):

  • Leader 將 nextIndex 遞減并重發(fā) AppendEntries,直到與 leader 日志一致

Commit Index 推進(jìn)

CommitIndex (TermId, LogIndex) :

  • 所謂 commitIndex,就是已達(dá)成多數(shù)派,可以應(yīng)用到狀態(tài)機(jī)的最新的日志位置
  • 日志被復(fù)制到 followers 后,先持久化,并不能馬上被應(yīng)用到狀態(tài)機(jī)
  • 只有 leader 知道日志是否達(dá)成多數(shù)派,是否可以應(yīng)用到狀態(tài)機(jī)
  • Followers 記錄 leader 發(fā)來的當(dāng)前 commitIndex,所有小于等于 commitIndex 的日志均可以應(yīng)用到狀態(tài)機(jī)

CommitIndex推進(jìn):

  • Leader 在下一個(gè) AppendEntries RPC (也包括 Heartbeat)中攜帶當(dāng)前的 commitIndex
  • Followers 檢查日志有效性通過則接受 AppendEntries 并同時(shí)更新本地 commitIndex, 最后把所有小于等于 commitIndex 的日志應(yīng)用到狀態(tài)機(jī)

AppendEntries RPC

  • 完整信息:(currentTerm, logEntries[], prevTerm, prevLogIndex, commitTerm, commitLogIndex)
  • currentTerm, logEntries[]:日志信息,為了效率,日志通常為多條
  • prevTerm, prevLogIndex:日志有效性檢查
  • commitTerm, commitLogIndex:最新的提交日志位點(diǎn)(commitIndex)

階段小結(jié):現(xiàn)在我們能用 raft 做什么?

  • 連續(xù)確定多個(gè)提案,確保集群中各個(gè)系統(tǒng)節(jié)點(diǎn)狀態(tài)完全一致
  • 自動(dòng)選主,保證在只有少數(shù)派宕機(jī)的情況下持續(xù)可用
  • 日志強(qiáng)同步,宕機(jī)后零數(shù)據(jù)丟失

三 SOFAJRaft

一個(gè)純 Java 的 raft 算法實(shí)現(xiàn)庫(kù),使用 Java 重寫了所有功能,并有一些改進(jìn)和優(yōu)化。

1 SOFAJRaft 整體功能

功能支持

Leader election:選主。

Log replication and recovery:日志復(fù)制和日志恢復(fù),log recovery就是要保證已經(jīng)被 commit 的數(shù)據(jù)一定不會(huì)丟失,log recovery 包含兩個(gè)方面

  • Current term 日志恢復(fù),主要針對(duì)一些 follower 節(jié)點(diǎn)重啟加入集群或者是新增 follower 節(jié)點(diǎn)
  • Prev term 日志恢復(fù),主要針對(duì) leader 切換前后的日志一致性

Snapshot and log compaction:定時(shí)生成 snapshot,實(shí)現(xiàn) log compaction加速啟動(dòng)和恢復(fù),以及InstallSnapshot 給 followers 拷貝數(shù)據(jù)。

Membership change:集群線上配置變更,增加節(jié)點(diǎn)、刪除節(jié)點(diǎn)、替換節(jié)點(diǎn)等。

Transfer leader:主動(dòng)變更 leader,用于重啟維護(hù),leader 負(fù)載平衡等。

Symmetric network partition tolerance:對(duì)稱網(wǎng)絡(luò)分區(qū)容忍性。

Pre-Vote:如上圖 S1 為當(dāng)前 leader,網(wǎng)絡(luò)分區(qū)造成 S2 不斷增加本地 term,為了避免網(wǎng)絡(luò)恢復(fù)后S2發(fā)起選舉導(dǎo)致正在良心工作的 leader step-down, 從而導(dǎo)致整個(gè)集群重新發(fā)起選舉,在 request-vote 之前會(huì)先進(jìn)行 pre-vote(currentTerm + 1,lastLogIndex, lastLogTerm),多數(shù)派成功后才會(huì)轉(zhuǎn)換狀態(tài)為 candidate 發(fā)起真正的 request-vote,所以分區(qū)后的節(jié)點(diǎn),pre-vote不會(huì)成功,也就不會(huì)導(dǎo)致集群一段時(shí)間內(nèi)無法正常提供服務(wù)。

Asymmetric network partition tolerance:非對(duì)稱網(wǎng)絡(luò)分區(qū)容忍性。

如上圖 S1 為當(dāng)前 leader,S2 不斷超時(shí)觸發(fā)選主,S3 提升 term 打斷當(dāng)前 lease,從而拒絕 leader 的更新,這個(gè)時(shí)候可以增加一個(gè) trick 的檢查,每個(gè) follower 維護(hù)一個(gè)時(shí)間戳記錄收到 leader 上數(shù)據(jù)更新的時(shí)間(也包括心跳),只有超過 election timeout 之后才允許接受 request-vote 請(qǐng)求。

Fault tolerance:容錯(cuò)性,少數(shù)派故障,不影響系統(tǒng)整體可用性。

  • 機(jī)器掉電
  • 強(qiáng)殺應(yīng)用
  • 慢節(jié)點(diǎn)(GC, OOM等)
  • 網(wǎng)絡(luò)故障
  • 其他各種奇葩原因?qū)е?raft 節(jié)點(diǎn)無法正常工作

Workaround when quorate peers are dead:多數(shù)派故障時(shí)整個(gè) grop 已不具備可用性, 安全的做法是等待多數(shù)節(jié)點(diǎn)恢復(fù),只有這樣才能保證數(shù)據(jù)安全,但是如果業(yè)務(wù)更追求可用性,放棄數(shù)據(jù)一致性的話可以通過手動(dòng) reset_peers 指令迅速重建整個(gè)集群,恢復(fù)集群可用。

Metrics:SOFAJRaft 內(nèi)置了基于 metrics 類庫(kù)的性能指標(biāo)統(tǒng)計(jì),具有豐富的性能統(tǒng)計(jì)指標(biāo)。

Jepsen:除了單元測(cè)試之外,SOFAJRaft 還使用 jepsen 這個(gè)分布式驗(yàn)證和故障注入測(cè)試框架模擬了很多種情況,都已驗(yàn)證通過。

隨機(jī)分區(qū),一大一小兩個(gè)網(wǎng)絡(luò)分區(qū)

  • 隨機(jī)增加和移除節(jié)點(diǎn)
  • 隨機(jī)停止和啟動(dòng)節(jié)點(diǎn)
  • 隨機(jī) kill -9 和啟動(dòng)節(jié)點(diǎn)
  • 隨機(jī)劃分為兩組,互通一個(gè)中間節(jié)點(diǎn),模擬分區(qū)情況
  • 隨機(jī)劃分為不同的 majority 分組

性能優(yōu)化

Batch:SOFAJRaft 中整個(gè)鏈路都是 batch 的,依靠 disruptor 中的 MPSC 模型批量消費(fèi),包括但不限于

  • 批量提交 task
  • 批量網(wǎng)絡(luò)發(fā)送
  • 本地 IO batch 寫入,要保證日志不丟,一般每一條 log entry 都要進(jìn)行 fsync, 比較耗時(shí),SOFAJRaft 中做了合并寫入的優(yōu)化
  • 批量應(yīng)用到狀態(tài)機(jī)

Replication pipeline:流水線復(fù)制,leader 跟 followers 節(jié)點(diǎn)的 log 同步是串行 batch 的方式,每個(gè) batch 發(fā)送之后需要等待 batch 同步完成之后才能繼續(xù)發(fā)送下一批(ping-pong), 這樣會(huì)導(dǎo)致較長(zhǎng)的延遲??梢酝ㄟ^ leader 跟 followers 節(jié)點(diǎn)之間的 pipeline 復(fù)制來改進(jìn),有效降低更新的延遲, 提高吞吐。

Append log in parallel:Leader 持久化 log entries 和向 followers 發(fā)送 log entries 是并行的。

Fully concurrent replication:Leader 向所有 follwers 發(fā)送 log 也是完全并發(fā)的。

Asynchronous:Jraft 中整個(gè)鏈路幾乎沒有任何阻塞,完全異步的,是一個(gè) callback 編程模型。

ReadIndex:優(yōu)化 raft read 走 raft log 的性能問題,每次 read,僅記錄 commitIndex,然后發(fā)送所有 peers heartbeat 來確認(rèn) leader 身份,如果 leader 身份確認(rèn)成功,等到 applied index >= commitIndex,就可以返回 client read 了,基于 ReadIndex 可以很方便的提供線性一致讀,不過 commitIndex 是需要從 leader 那里獲取的,多了一輪RPC。

Lease Read:通過租約(lease)保證 leader 的身份,從而省去了 readIndex 每次 heartbeat 確認(rèn) leader 身份,性能更好, 但是通過時(shí)鐘維護(hù) lease 本身并不是絕對(duì)的安全(jraft 中默認(rèn)配置是 readIndex,因?yàn)?readIndex 性能已足夠好)。

2 SOFAJRaft 設(shè)計(jì)

SOFAJRaft - Raft Node

Node:Raft 分組中的一個(gè)節(jié)點(diǎn),連接封裝底層的所有服務(wù),用戶看到的主要服務(wù)接口,特別是 apply(task) 用于向 raft group 組成的復(fù)制狀態(tài)機(jī)集群提交新任務(wù)應(yīng)用到業(yè)務(wù)狀態(tài)機(jī)。

存儲(chǔ):

  • Log 存儲(chǔ),記錄 raft 用戶提交任務(wù)的日志,將從 leader 復(fù)制到其他節(jié)點(diǎn)上。LogStorage 是存儲(chǔ)實(shí)現(xiàn), LogManager 負(fù)責(zé)對(duì)底層存儲(chǔ)的調(diào)用,對(duì)調(diào)用做緩存、批量提交、必要的檢查和優(yōu)化。
  • Metadata 存儲(chǔ),元信息存儲(chǔ),記錄 raft 實(shí)現(xiàn)的內(nèi)部狀態(tài),比如當(dāng)前 term、投票給哪個(gè)節(jié)點(diǎn)等信息。
  • Snapshot 存儲(chǔ),用于存放用戶的狀態(tài)機(jī) snapshot 及元信息,可選. SnapshotStorage 用于 snapshot 存儲(chǔ)實(shí)現(xiàn),SnapshotExecutor 用于 snapshot 實(shí)際存儲(chǔ)、遠(yuǎn)程安裝、復(fù)制的管理。

狀態(tài)機(jī):

  • StateMachine:用戶核心邏輯的實(shí)現(xiàn),核心是 onApply(Iterator) 方法,應(yīng)用通過 Node#apply(task) 提交的日志到業(yè)務(wù)狀態(tài)機(jī)。
  • FSMCaller:封裝對(duì)業(yè)務(wù) StateMachine 的狀態(tài)轉(zhuǎn)換的調(diào)用以及日志的寫入等,一個(gè)有限狀態(tài)機(jī)的實(shí)現(xiàn), 做必要的檢查、請(qǐng)求合并提交和并發(fā)處理等。

復(fù)制:

  • Replicator:用于 leader 向 followers 復(fù)制日志,也就是 raft 中的 AppendEntries 調(diào)用,包括心跳存活檢查等。
  • ReplicatorGroup:用于單個(gè) raft group 管理所有的 replicator,必要的權(quán)限檢查和派發(fā)。

RPC 模塊用于節(jié)點(diǎn)之間的網(wǎng)絡(luò)通訊:

  • RPC Server:內(nèi)置于 Node 內(nèi)的 RPC 服務(wù)器,接收其他節(jié)點(diǎn)或者客戶端發(fā)過來的請(qǐng)求, 轉(zhuǎn)交給對(duì)應(yīng)服務(wù)處理。
  • RPC Client:用于向其他節(jié)點(diǎn)發(fā)起請(qǐng)求,例如投票、復(fù)制日志、心跳等。

KV Store:SOFAJRaft 只是一個(gè) lib,KV Store 是 SOFAJRaft 的一個(gè)典型的應(yīng)用場(chǎng)景,把它放進(jìn)圖中以便更好的理解 SOFAJRaft。

SOFAJRaft - Raft Group

SOFAJRaft - Multi Raft Group

3 SOFAJRaft 實(shí)現(xiàn)細(xì)節(jié)

高效的線性一致讀

什么是線性一致讀?

所謂線性一致讀,一個(gè)簡(jiǎn)單的例子就是在 t1 的時(shí)刻我們寫入了一個(gè)值, 那么在 t1 之后, 我們一定能讀到這個(gè)值,不可能讀到 t1 之前的舊值 (想想 Java 中的 volatile 關(guān)鍵字,說白了線性一致讀就是在分布式系統(tǒng)中實(shí)現(xiàn) volatile 語義)。

上圖Client A、B、C、D均符合線性一致讀,其中 D 看起來是 stale read,其實(shí)并不是, D 請(qǐng)求橫跨了3個(gè)階段,而讀可能發(fā)生在任意時(shí)刻,所以讀到 1 或 2 都行。

重要:接下來的討論均基于一個(gè)大前提,就是業(yè)務(wù)狀態(tài)機(jī)的實(shí)現(xiàn)必須是滿足線性一致性的, 簡(jiǎn)單說就是也要具有 Java volatile 的語義。

1)直接點(diǎn),是否可以直接從當(dāng)前 leader 節(jié)點(diǎn)讀?

怎么確定當(dāng)前的 leader 真的是 leader(網(wǎng)絡(luò)分區(qū))?

2)最簡(jiǎn)單的實(shí)現(xiàn)方式:讀請(qǐng)求走一遍 raft 協(xié)議

有什么問題?

  • 不僅有日志寫盤開銷,還有日志復(fù)制的 RPC 開銷,在讀比重較大的系統(tǒng)中是無法接受的
  • 還多了一堆的 raft “讀日志”

3)ReadIndex Read

這是 raft 論文中提到過的一種優(yōu)化方案,具體來說:

  • 將當(dāng)前自己 log 的 commit index 記錄到一個(gè) local 變量 ReadIndex 里面。
  • 向其他節(jié)點(diǎn)發(fā)起一次 heartbeat,如果大多數(shù)節(jié)點(diǎn)返回了對(duì)應(yīng)的 heartbeat response,那么 leader 就能夠確定現(xiàn)在自己仍然是 leader (證明了自己是自己)。
  • Leader 等待自己的狀態(tài)機(jī)執(zhí)行,直到 apply index 超過了 ReadIndex,這樣就能夠安全的提供 Linearizable Read 了, 也不必管讀的時(shí)刻是否 leader 已飄走 (思考:為什么需要等到 apply index 超過了 ReadIndex 才可以執(zhí)行讀請(qǐng)求?)。
  • Leader 執(zhí)行 read 請(qǐng)求,將結(jié)果返回給 Client。

通過ReadIndex,也可以很容易在 followers 節(jié)點(diǎn)上提供線性一致讀:

  • Follower 節(jié)點(diǎn)向 leader 請(qǐng)求最新的 ReadIndex。
  • Leader執(zhí)行上面 i ~ iii 的過程(確定自己真的是 leader),并返回 ReadIndex 給 follower。
  • Follower 等待自己的 apply index 超過了 ReadIndex (有什么問題?慢節(jié)點(diǎn)?)。
  • Follower 執(zhí)行 read 請(qǐng)求,將結(jié)果返回給 client。

ReadIndex小結(jié):

  • 相比較于走 raft log 的方式,ReadIndex 讀省去了磁盤的開銷,能大幅度提升吞吐,結(jié)合 SOFAJRaft 的 batch + pipeline ack + 全異步機(jī)制,三副本的情況下 leader 讀的吞吐接近于 RPC 的上限。
  • 延遲取決于多數(shù)派中最慢的一個(gè) heartbeat response,理論上對(duì)于降低延時(shí)的效果不會(huì)非常顯著。

4)Lease Read

Lease read 與 ReadIndex 類似,但更進(jìn)一步,不僅省去了 log,還省去了網(wǎng)絡(luò)交互。它可以大幅提升讀的吞吐也能顯著降低延時(shí)。

基本的思路是 leader 取一個(gè)比 election timeout 小的租期(最好小一個(gè)數(shù)量級(jí)),在租約期內(nèi)不會(huì)發(fā)生選舉,這就確保了 leader 不會(huì)變,所以可以跳過 ReadIndex 的第二步, 也就降低了延時(shí)??梢钥吹? Lease read 的正確性和時(shí)間是掛鉤的,因此時(shí)間的實(shí)現(xiàn)至關(guān)重要,如果漂移嚴(yán)重,這套機(jī)制就會(huì)有問題。

實(shí)現(xiàn)方式:

  • 定時(shí) heartbeat 獲得多數(shù)派響應(yīng), 確認(rèn) leader 的有效性 (在 SOFAJRaft 中默認(rèn)的 heartbeat 間隔是 election timeout 的十分之一)。
  • 在租約有效時(shí)間內(nèi),可以認(rèn)為當(dāng)前 leader 是 raft group 內(nèi)的唯一有效 leader,可忽略 ReadIndex 中的 heartbeat 確認(rèn)步驟(2)。
  • Leader 等待自己的狀態(tài)機(jī)執(zhí)行,直到 apply index 超過了 ReadIndex,這樣就能夠安全的提供 Linearizable Read 了。

5)更進(jìn)一步:Wait Free

到此為止 lease 省去了 ReadIndex 的第 2 步(heartbeat),實(shí)際上還能再進(jìn)一步,省去第 3 步。

我們想想前面的實(shí)現(xiàn)方案的本質(zhì)是什么? 當(dāng)前節(jié)點(diǎn)的狀態(tài)機(jī)達(dá)到“讀”這一刻的時(shí)間點(diǎn) 相同或者更新的狀態(tài)。

那么更嚴(yán)格一點(diǎn)的約束就是:當(dāng)前時(shí)刻,當(dāng)前節(jié)點(diǎn)的狀態(tài)機(jī)就是最新的。

問題來了,leader 節(jié)點(diǎn)的狀態(tài)機(jī)能保證一定是最新的嗎?

  • 首先 leader 節(jié)點(diǎn)的 log 一定是最新的,即使新選舉產(chǎn)生的 leader,它也一定包含全部的 commit log,但它的狀態(tài)機(jī)卻可能落后于舊的 leader。
  • 但是在 leader 應(yīng)用了自己當(dāng)前 term 的第一條 log 之后,它的狀態(tài)機(jī)就一定是最新的。
  • 所以可以得出結(jié)論:當(dāng) leader 已經(jīng)成功應(yīng)用了自己 term 的第一條 log 之后,不需要再取 commit index,也不用等狀態(tài)機(jī),直接讀,一定是線性一致讀。

小結(jié):Wait Free 機(jī)制將最大程度的降低讀延遲,SOFAJRaft 暫未實(shí)現(xiàn) wait free 這一優(yōu)化,不過已經(jīng)在計(jì)劃中。

在 SOFAJRaft 中發(fā)起一次線性一致讀請(qǐng)求:

  1. // KV 存儲(chǔ)實(shí)現(xiàn)線性一致讀 
  2. public void readFromQuorum(String key, AsyncContext asyncContext) { 
  3.     // 請(qǐng)求 ID 作為請(qǐng)求上下文傳入 
  4.     byte[] reqContext = new byte[4]; 
  5.     Bits.putInt(reqContext, 0, requestId.incrementAndGet()); 
  6.     // 調(diào)用 readIndex 方法, 等待回調(diào)執(zhí)行 
  7.     this.node.readIndex(reqContext, new ReadIndexClosure() { 
  8.  
  9.         @Override 
  10.         public void run(Status status, long index, byte[] reqCtx) { 
  11.             if (status.isOk()) { 
  12.                 try { 
  13.                     // ReadIndexClosure 回調(diào)成功, 可以從狀態(tài)機(jī)讀取最新數(shù)據(jù)返回 
  14.                     // 如果你的狀態(tài)實(shí)現(xiàn)有版本概念, 可以根據(jù)傳入的日志 index 編號(hào)做讀取 
  15.                     asyncContext.sendResponse(new ValueCommand(fsm.getValue(key))); 
  16.                 } catch (KeyNotFoundException e) { 
  17.                     asyncContext.sendResponse(GetCommandProcessor.createKeyNotFoundResponse()); 
  18.                 } 
  19.             } else { 
  20.                 // 特定情況下, 比如發(fā)生選舉, 該讀請(qǐng)求將失敗 
  21.                 asyncContext.sendResponse(new BooleanCommand(false, status.getErrorMsg())); 
  22.             } 
  23.         } 
  24.     }); 

四 SOFAJRaft 應(yīng)用場(chǎng)景

1 SOFAJRaft 可以做什么

  • 選舉
  • 分布式鎖服務(wù),比如 zookeeper
  • 高可靠的元信息管理
  • 分布式存儲(chǔ)系統(tǒng),如分布式消息隊(duì)列、分布式文件系統(tǒng)、分布式塊系統(tǒng)等等。

2 用戶案例

  • AntQ Streams QCoordinator:使用 SOFAJRaft 在 coordinator 集群內(nèi)做選舉、元信息存儲(chǔ)等功能。
  • Schema Registry:高可靠 schema 管理服務(wù),類似 kafka schema registry。
  • SOFA 服務(wù)注冊(cè)中心元信息管理模塊:IP 數(shù)據(jù)信息注冊(cè),要求寫數(shù)據(jù)達(dá)到各個(gè)節(jié)點(diǎn)一致, 并且在少數(shù)派節(jié)點(diǎn)掛掉時(shí)保證不影響數(shù)據(jù)正常存儲(chǔ)。
  • RheaKV:基于 SOFAJRaft 和 rocksDB 實(shí)現(xiàn)的嵌入式、分布式、高可用、強(qiáng)一致的 KV 存儲(chǔ)類庫(kù)。

3 簡(jiǎn)單實(shí)踐:基于 SOFAJRaft 設(shè)計(jì)一個(gè)簡(jiǎn)單的 KV Store

到目前為止,我們似乎還沒看到 SOFAJRaft 作為一個(gè) lib 有什么特別之處, 因?yàn)?SOFAJRaft 能辦到的 zk,etcd 似乎基本上也都可以辦到, 那么 SOFAJRaft 算不算重復(fù)造輪子?

為了說明 SOFAJRaft 具有很好的想象空間以及擴(kuò)展能力,下面再介紹一個(gè)基于 SOFAJRaft 的復(fù)雜一些的實(shí)踐。

4 復(fù)雜一點(diǎn)的實(shí)踐:基于 SOFAJRaft 的 Rhea KV 的設(shè)計(jì)

功能名詞

  • PD:全局的中心總控節(jié)點(diǎn), 負(fù)責(zé)整個(gè)集群的調(diào)度, 不需要自管理的集群可不啟用 PD (一個(gè)PD可管理多個(gè)集群,基于 clusterId 隔離)。
  • Store:集群中的一個(gè)物理存儲(chǔ)節(jié)點(diǎn),一個(gè) store 包含一個(gè)或多個(gè) region。
  • Region:最小的 KV 數(shù)據(jù)單元,每個(gè) region 都有一個(gè)左閉右開的區(qū)間 [startKey, endKey),可根據(jù)請(qǐng)求流量/負(fù)載/數(shù)據(jù)量大小等指標(biāo)自動(dòng)分裂以及自動(dòng)副本搬遷。

特點(diǎn)

  • 嵌入式
  • 強(qiáng)一致性
  • 自驅(qū)動(dòng):自診斷,自優(yōu)化,自決策,自恢復(fù)。以上幾點(diǎn)(尤其2, 3)基本都是依托于 SOFAJRaft 自身的功能來實(shí)現(xiàn)。

 

責(zé)任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2024-05-27 10:42:55

2019-10-11 23:27:19

分布式一致性算法開發(fā)

2020-05-11 10:30:57

2PC分布式協(xié)議

2019-09-05 08:43:34

微服務(wù)分布式一致性數(shù)據(jù)共享

2021-11-22 16:30:30

分布式一致性分布式系統(tǒng)

2017-09-21 10:59:36

分布式系統(tǒng)線性一致性測(cè)試

2024-11-28 10:56:55

2021-07-28 08:39:25

分布式架構(gòu)系統(tǒng)

2022-06-07 12:08:10

Paxos算法

2020-05-29 14:46:23

3PC協(xié)議分布式系統(tǒng)

2025-03-27 03:00:00

2021-06-06 12:45:41

分布式CAPBASE

2017-09-22 12:08:01

數(shù)據(jù)庫(kù)分布式系統(tǒng)互聯(lián)網(wǎng)

2020-10-28 11:15:24

EPaxos分布式性算法

2023-11-06 09:06:54

分布式一致性數(shù)據(jù)

2020-03-16 11:55:28

PaxosRaft協(xié)議

2021-08-13 07:56:13

Raft算法日志

2023-08-15 09:31:01

分布式緩存

2021-06-16 08:33:02

分布式事務(wù)ACID

2021-08-13 11:50:23

AnalyticDB 分布式數(shù)據(jù)庫(kù)
點(diǎn)贊
收藏

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