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

螞蟻金服開(kāi)源 SOFAJRaft:生產(chǎn)級(jí) Java Raft 算法庫(kù)

新聞 前端 算法
SOFAJRaft 是一個(gè)基于 Raft 一致性算法的生產(chǎn)級(jí)高性能 Java 實(shí)現(xiàn),支持 MULTI-RAFT-GROUP,適用于高負(fù)載低延遲的場(chǎng)景。

什么是 SOFAJRaft?

SOFAJRaft 是一個(gè)基于 Raft 一致性算法的生產(chǎn)級(jí)高性能 Java 實(shí)現(xiàn),支持 MULTI-RAFT-GROUP,適用于高負(fù)載低延遲的場(chǎng)景。 使用 SOFAJRaft 你可以專(zhuān)注于自己的業(yè)務(wù)領(lǐng)域,由 SOFAJRaft 負(fù)責(zé)處理所有與 Raft 相關(guān)的技術(shù)難題,并且 SOFAJRaft 非常易于使用,你可以通過(guò)幾個(gè)示例在很短的時(shí)間內(nèi)掌握它。

https://raft.github.io

SOFAJRaft 是從百度的 braft 移植而來(lái),做了一些優(yōu)化和改進(jìn),感謝百度 braft 團(tuán)隊(duì)開(kāi)源了如此優(yōu)秀的 C++ Raft 實(shí)現(xiàn)。

https://github.com/brpc/braft

基礎(chǔ)知識(shí):分布式共識(shí)算法 (Consensus Algorithm)

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

  • 多個(gè)參與者某一件事一致 :一件事,一個(gè)結(jié)論
  • 已達(dá)成一致的結(jié)論,不可推翻

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

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

什么是 Raft?

Raft 是一種更易于理解的分布式共識(shí)算法,核心協(xié)議本質(zhì)上還是師承 Paxos 的精髓,不同的是依靠 Raft 模塊化的拆分以及更加簡(jiǎn)化的設(shè)計(jì),Raft 協(xié)議相對(duì)更容易實(shí)現(xiàn)。

https://raft.github.io/

模塊化的拆分主要體現(xiàn)在:Raft 把一致性協(xié)議劃分為 Leader 選舉、MemberShip 變更、日志復(fù)制、Snapshot 等幾個(gè)幾乎完全解耦的模塊。

更加簡(jiǎn)化的設(shè)計(jì)則體現(xiàn)在:Raft 不允許類(lèi)似 Paxos 中的亂序提交、簡(jiǎn)化系統(tǒng)中的角色狀態(tài)(只有 Leader、Follower、Candidate 三種角色)、限制僅 Leader 可寫(xiě)入、使用隨機(jī)化的超時(shí)時(shí)間來(lái)設(shè)計(jì) Leader Election 等等。

特點(diǎn):Strong Leader

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

一句話(huà)總結(jié) Strong Leader: "你們不要 BB! 按我說(shuō)的做,做完了向我匯報(bào)!"。

另外,身為 Leader 必須保持一直 BB(heartbeat) 的狀態(tài),否則就會(huì)有別人跳出來(lái)想要 BB 。

螞蟻金服開(kāi)源 SOFAJRaft:生產(chǎn)級(jí) Java Raft 算法庫(kù)

Raft 中的基本概念

篇幅有限,這里只對(duì) Raft 中的幾個(gè)概念做一個(gè)簡(jiǎn)單介紹,詳細(xì)請(qǐng)參考 Raft paper。

https://raft.github.io/raft.pdf

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

螞蟻金服開(kāi)源 SOFAJRaft:生產(chǎn)級(jí) Java Raft 算法庫(kù)
  1. Follower:完全被動(dòng),不能發(fā)送任何請(qǐng)求,只接受并響應(yīng)來(lái)自 Leader 和 Candidate 的 Message,每個(gè)節(jié)點(diǎn)啟動(dòng)后的初始狀態(tài)一定是 Follower;
  2. Leader:處理所有來(lái)自客戶(hù)端的請(qǐng)求,以及復(fù)制 Log 到所有 Followers;
  3. Candidate:用來(lái)競(jìng)選一個(gè)新 Leader (Candidate 由 Follower 觸發(fā)超時(shí)而來(lái))。

Message 的 3 種類(lèi)型

  1. RequestVote RPC:由 Candidate 發(fā)出,用于發(fā)送投票請(qǐng)求;
  2. AppendEntries (Heartbeat) RPC:由 Leader 發(fā)出,用于 Leader 向 Followers 復(fù)制日志條目,也會(huì)用作 Heartbeat (日志條目為空即為 Heartbeat);
  3. InstallSnapshot RPC:由 Leader 發(fā)出,用于快照傳輸,雖然多數(shù)情況都是每個(gè)服務(wù)器獨(dú)立創(chuàng)建快照,但是Leader 有時(shí)候必須發(fā)送快照給一些落后太多的 Follower,這通常發(fā)生在 Leader 已經(jīng)丟棄了下一條要發(fā)給該Follower 的日志條目(Log Compaction 時(shí)清除掉了) 的情況下。

任期邏輯時(shí)鐘

  1. 時(shí)間被劃分為一個(gè)個(gè)任期 (term),term id 按時(shí)間軸單調(diào)遞增;
  2. 每一個(gè)任期的開(kāi)始都是 Leader 選舉,選舉成功之后,Leader 在任期內(nèi)管理整個(gè)集群,也就是 “選舉 + 常規(guī)操作”;
  3. 每個(gè)任期最多一個(gè) Leader,可能沒(méi)有 Leader (spilt-vote 導(dǎo)致)。
螞蟻金服開(kāi)源 SOFAJRaft:生產(chǎn)級(jí) Java Raft 算法庫(kù)

本圖出自《Raft: A Consensus Algorithm for Replicated Logs》

什么是 SOFAJRaft?

SOFAJRaft 是一個(gè)基于 Raft 一致性算法的生產(chǎn)級(jí)高性能 Java 實(shí)現(xiàn),支持 MULTI-RAFT-GROUP,適用于高負(fù)載低延遲的場(chǎng)景。 使用 SOFAJRaft 你可以專(zhuān)注于自己的業(yè)務(wù)領(lǐng)域,由 SOFAJRaft 負(fù)責(zé)處理所有與 Raft 相關(guān)的技術(shù)難題,并且 SOFAJRaft 非常易于使用,你可以通過(guò)幾個(gè)示例在很短的時(shí)間內(nèi)掌握它。

https://github.com/brpc/braft

SOFAJRaft 是從百度的 braft 移植而來(lái),做了一些優(yōu)化和改進(jìn),感謝百度 braft 團(tuán)隊(duì)開(kāi)源了如此優(yōu)秀的 C++ Raft 實(shí)現(xiàn)。

SOFAJRaft 整體功能&性能優(yōu)化

螞蟻金服開(kāi)源 SOFAJRaft:生產(chǎn)級(jí) Java Raft 算法庫(kù)

功能支持

1.Leader election:Leader 選舉,這個(gè)不多說(shuō),上面已介紹過(guò) Raft 中的 Leader 機(jī)制。

2.Log replication and recovery:日志復(fù)制和日志恢復(fù)。

1)Log replication 就是要保證已經(jīng)被 commit 的數(shù)據(jù)一定不會(huì)丟失,即一定要成功復(fù)制到多數(shù)派。

2)Log recovery 包含兩個(gè)方面:

3)Current term 日志恢復(fù):主要針對(duì)一些 Follower 節(jié)點(diǎn)重啟加入集群或者是新增 Follower 節(jié)點(diǎn)后如何追日志;

4)Prev term 日志恢復(fù):主要針對(duì) Leader 切換前后的日志一致性。

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

螞蟻金服開(kāi)源 SOFAJRaft:生產(chǎn)級(jí) Java Raft 算法庫(kù)

本圖出自《In Search of an Understandable Consensus Algorithm》

4.Membership change:用于集群線(xiàn)上配置變更,比如增加節(jié)點(diǎn)、刪除節(jié)點(diǎn)、替換節(jié)點(diǎn)等。

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

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

螞蟻金服開(kāi)源 SOFAJRaft:生產(chǎn)級(jí) Java Raft 算法庫(kù)

如上圖 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ā)起選舉,SOFAJRaft 中增加了 pre-vote 來(lái)避免這個(gè)問(wèn)題的發(fā)生。

SOFAJRaft 中在 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ú)法正常提供服務(wù)。

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

螞蟻金服開(kāi)源 SOFAJRaft:生產(chǎn)級(jí) Java Raft 算法庫(kù)

如上圖 S1 為當(dāng)前 leader,S2 不斷超時(shí)觸發(fā)選主,S3 提升 term 打斷當(dāng)前 lease,從而拒絕 leader 的更新。

  1. 在 SOFAJRaft 中增加了一個(gè) tick 的檢查,每個(gè) follower 維護(hù)一個(gè)時(shí)間戳記錄下收到 leader 上數(shù)據(jù)更新的時(shí)間(也包括心跳),只有超過(guò) election timeout 之后才允許接受 request-vote 請(qǐng)求。

8.Fault tolerance:容錯(cuò)性,少數(shù)派故障不影響系統(tǒng)整體可用性,包括但不限于:

1)機(jī)器掉電

2)強(qiáng)殺應(yīng)用

3)慢節(jié)點(diǎn)(GC, OOM 等)

4)網(wǎng)絡(luò)故障

5)其他各種奇葩原因?qū)е?raft 節(jié)點(diǎn)無(wú)法正常工作

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

10.Metrics:SOFAJRaft 內(nèi)置了基于 Metrics 類(lèi)庫(kù)的性能指標(biāo)統(tǒng)計(jì),具有豐富的性能統(tǒng)計(jì)指標(biāo),利用這些指標(biāo)數(shù)據(jù)可以幫助用戶(hù)更容易找出系統(tǒng)性能瓶頸。

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

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

2)隨機(jī)增加和移除節(jié)點(diǎn)

3)隨機(jī)停止和啟動(dòng)節(jié)點(diǎn)

4)隨機(jī) kill -9 和啟動(dòng)節(jié)點(diǎn)

5)隨機(jī)劃分為兩組,互通一個(gè)中間節(jié)點(diǎn),模擬分區(qū)情況

6)隨機(jī)劃分為不同的 majority 分組

性能優(yōu)化

除了功能上的完整性,SOFAJRaft 還做了很多性能方面的優(yōu)化,這里有一份 KV 場(chǎng)景(get/put)的 Benchmark 數(shù)據(jù), 在小數(shù)據(jù)包,讀寫(xiě)比例為 9:1,保證線(xiàn)性一致讀的場(chǎng)景下,三副本***可以達(dá)到 40w+ 的 ops。

這里挑重點(diǎn)介紹幾個(gè)優(yōu)化點(diǎn):

  1. Batch: 我們知道互聯(lián)網(wǎng)兩大優(yōu)化法寶便是 Cache 和 Batch,SOFAJRaft 在 Batch 上花了較大心思,整個(gè)鏈路幾乎都是 Batch 的,依靠 disruptor 的 MPSC 模型批量消費(fèi),對(duì)整體性能有著極大的提升,包括但不限于:
  2. 批量提交 task
  3. 批量網(wǎng)絡(luò)發(fā)送
  4. 本地 IO batch 寫(xiě)入
  5. 要保證日志不丟,一般每條 log entry 都要進(jìn)行 fsync 同步刷盤(pán),比較耗時(shí),SOFAJRaft 中做了合并寫(xiě)入的優(yōu)化。
  6. 批量應(yīng)用到狀態(tài)機(jī)
  7. 需要說(shuō)明的是,雖然 SOFAJRaft 中大量使用了 Batch 技巧,但對(duì)單個(gè)請(qǐng)求的延時(shí)并無(wú)任何影響,SOFAJRaft 中不會(huì)對(duì)請(qǐng)求做延時(shí)的攢批處理。
  8. Replication pipeline:流水線(xiàn)復(fù)制,通常 Leader 跟 Followers 節(jié)點(diǎn)的 Log 同步是串行 Batch 的方式,每個(gè) Batch 發(fā)送之后需要等待 Batch 同步完成之后才能繼續(xù)發(fā)送下一批(ping-pong),這樣會(huì)導(dǎo)致較長(zhǎng)的延遲。SOFAJRaft 中通過(guò) Leader 跟 Followers 節(jié)點(diǎn)之間的 pipeline 復(fù)制來(lái)改進(jìn),非常有效降低了數(shù)據(jù)同步的延遲, 提高吞吐。經(jīng)我們測(cè)試,開(kāi)啟 pipeline 可以將吞吐提升 30% 以上,詳細(xì)數(shù)據(jù)請(qǐng)參照 Benchmark。
  9. Append log in parallel:在 SOFAJRaft 中 Leader 持久化 log entries 和向 Followers 發(fā)送 log entries 是并行的。
  10. Fully concurrent replication:Leader 向所有 Follwers 發(fā)送 Log 也是完全相互獨(dú)立和并發(fā)的。
  11. Asynchronous:SOFAJRaft 中整個(gè)鏈路幾乎沒(méi)有任何阻塞,完全異步的,是一個(gè)完全的 callback 編程模型。
  12. ReadIndex:優(yōu)化 Raft read 走 Raft log 的性能問(wèn)題,每次 read,僅記錄 commitIndex,然后發(fā)送所有 peers heartbeat 來(lái)確認(rèn) Leader 身份,如果 Leader 身份確認(rèn)成功,等到 appliedIndex >= commitIndex,就可以返回 Client read 了,基于 ReadIndex Follower 也可以很方便的提供線(xiàn)性一致讀,不過(guò) commitIndex 是需要從 Leader 那里獲取,多了一輪 RPC;關(guān)于線(xiàn)性一致讀文章后面會(huì)詳細(xì)分析。
  13. Lease Read:SOFAJRaft 還支持通過(guò)租約 (lease) 保證 Leader 的身份,從而省去了 ReadIndex 每次 heartbeat 確認(rèn) Leader 身份,性能更好,但是通過(guò)時(shí)鐘維護(hù) lease 本身并不是絕對(duì)的安全(時(shí)鐘漂移問(wèn)題,所以 SOFAJRaft 中默認(rèn)配置是 ReadIndex,因?yàn)橥ǔG闆r下 ReadIndex 性能已足夠好。

SOFAJRaft 設(shè)計(jì)

螞蟻金服開(kāi)源 SOFAJRaft:生產(chǎn)級(jí) Java Raft 算法庫(kù)
  1. Node:Raft 分組中的一個(gè)節(jié)點(diǎn),連接封裝底層的所有服務(wù),用戶(hù)看到的主要服務(wù)接口,特別是 apply(task)用于向 raft group 組成的復(fù)制狀態(tài)機(jī)集群提交新任務(wù)應(yīng)用到業(yè)務(wù)狀態(tài)機(jī)。
  2. 存儲(chǔ):上圖靠下的部分均為存儲(chǔ)相關(guān)。
  3. Log 存儲(chǔ),記錄 Raft 用戶(hù)提交任務(wù)的日志,將日志從 Leader 復(fù)制到其他節(jié)點(diǎn)上。
  4. LogStorage 是存儲(chǔ)實(shí)現(xiàn),默認(rèn)實(shí)現(xiàn)基于 RocksDB 存儲(chǔ),你也可以很容易擴(kuò)展自己的日志存儲(chǔ)實(shí)現(xiàn);
  5. LogManager 負(fù)責(zé)對(duì)底層存儲(chǔ)的調(diào)用,對(duì)調(diào)用做緩存、批量提交、必要的檢查和優(yōu)化。
  6. Metadata 存儲(chǔ),元信息存儲(chǔ),記錄 Raft 實(shí)現(xiàn)的內(nèi)部狀態(tài),比如當(dāng)前 term、投票給哪個(gè)節(jié)點(diǎn)等信息。
  7. Snapshot 存儲(chǔ),用于存放用戶(hù)的狀態(tài)機(jī) snapshot 及元信息,可選:
  8. SnapshotStorage 用于 snapshot 存儲(chǔ)實(shí)現(xiàn);
  9. SnapshotExecutor 用于 snapshot 實(shí)際存儲(chǔ)、遠(yuǎn)程安裝、復(fù)制的管理。
  10. 狀態(tài)機(jī)
  11. StateMachine:用戶(hù)核心邏輯的實(shí)現(xiàn),核心是 onApply(Iterator) 方法, 應(yīng)用通過(guò) Node#apply(task) 提交的日志到業(yè)務(wù)狀態(tài)機(jī);
  12. FSMCaller:封裝對(duì)業(yè)務(wù) StateMachine 的狀態(tài)轉(zhuǎn)換的調(diào)用以及日志的寫(xiě)入等,一個(gè)有限狀態(tài)機(jī)的實(shí)現(xiàn),做必要的檢查、請(qǐng)求合并提交和并發(fā)處理等。
  13. 復(fù)制
  14. Replicator:用于 Leader 向 Followers 復(fù)制日志,也就是 Raft 中的 AppendEntries 調(diào)用,包括心跳存活檢查等;
  15. ReplicatorGroup:用于單個(gè) Raft group 管理所有的 replicator,必要的權(quán)限檢查和派發(fā)。
  16. RPC:RPC 模塊用于節(jié)點(diǎn)之間的網(wǎng)絡(luò)通訊
  17. RPC Server:內(nèi)置于 Node 內(nèi)的 RPC 服務(wù)器,接收其他節(jié)點(diǎn)或者客戶(hù)端發(fā)過(guò)來(lái)的請(qǐng)求,轉(zhuǎn)交給對(duì)應(yīng)服務(wù)處理;
  18. RPC Client:用于向其他節(jié)點(diǎn)發(fā)起請(qǐng)求,例如投票、復(fù)制日志、心跳等。
  19. KV Store:KV Store 是各種 Raft 實(shí)現(xiàn)的一個(gè)典型應(yīng)用場(chǎng)景,SOFAJRaft 中包含了一個(gè)嵌入式的分布式 KV 存儲(chǔ)實(shí)現(xiàn)(SOFAJRaft-RheaKV)。

SOFAJRaft Group

單個(gè)節(jié)點(diǎn)的 SOFAJRaft-node 是沒(méi)什么實(shí)際意義的,下面是三副本的 SOFAJRaft 架構(gòu)圖:

螞蟻金服開(kāi)源 SOFAJRaft:生產(chǎn)級(jí) Java Raft 算法庫(kù)

SOFAJRaft Multi Group

單個(gè) Raft group 是無(wú)法解決大流量的讀寫(xiě)瓶頸的,SOFAJRaft 自然也要支持 multi-raft-group。

螞蟻金服開(kāi)源 SOFAJRaft:生產(chǎn)級(jí) Java Raft 算法庫(kù)

SOFAJRaft 實(shí)現(xiàn)細(xì)節(jié)解析之高效的線(xiàn)性一致讀

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

螞蟻金服開(kāi)源 SOFAJRaft:生產(chǎn)級(jí) Java Raft 算法庫(kù)

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

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

  1. 要實(shí)現(xiàn)線(xiàn)性一致讀,首先我們簡(jiǎn)單直接一些,是否可以直接從當(dāng)前 Leader 節(jié)點(diǎn)讀?
  2. 仔細(xì)一想,這顯然行不通,因?yàn)槟銦o(wú)法確定這一刻當(dāng)前的 "Leader" 真的是 Leader,比如在網(wǎng)絡(luò)分區(qū)的情況下,它可能已經(jīng)被推翻王朝卻不自知。
  3. 最簡(jiǎn)單易懂的實(shí)現(xiàn)方式:同 “寫(xiě)” 請(qǐng)求一樣,“讀” 請(qǐng)求也走一遍 Raft 協(xié)議 (Raft Log)。
螞蟻金服開(kāi)源 SOFAJRaft:生產(chǎn)級(jí) Java Raft 算法庫(kù)

本圖出自《Raft: A Consensus Algorithm for Replicated Logs》

這一定是可以的,但性能上顯然不會(huì)太出色,走 Raft Log 不僅僅有日志落盤(pán)的開(kāi)銷(xiāo),還有日志復(fù)制的網(wǎng)絡(luò)開(kāi)銷(xiāo),另外還有一堆的 Raft “讀日志” 造成的磁盤(pán)占用開(kāi)銷(xiāo),這在讀比重很大的系統(tǒng)中通常是無(wú)法被接受的。

  1. ReadIndex Read
  2. 這是 Raft 論文中提到的一種優(yōu)化方案,具體來(lái)說(shuō):
  3. Leader 將自己當(dāng)前 Log 的 commitIndex 記錄到一個(gè) Local 變量 ReadIndex 里面;
  4. 接著向 Followers 發(fā)起一輪 heartbeat,如果半數(shù)以上節(jié)點(diǎn)返回了對(duì)應(yīng)的 heartbeat response,那么 Leader 就能夠確定現(xiàn)在自己仍然是 Leader (證明了自己是自己);
  5. Leader 等待自己的狀態(tài)機(jī)執(zhí)行,直到 applyIndex 超過(guò)了 ReadIndex,這樣就能夠安全的提供 Linearizable Read 了,也不必管讀的時(shí)刻是否 Leader 已飄走 (思考:為什么等到 applyIndex 超過(guò)了 ReadIndex 就可以執(zhí)行讀請(qǐng)求?);
  6. Leader 執(zhí)行 read 請(qǐng)求,將結(jié)果返回給 Client。
  7. 通過(guò)ReadIndex,也可以很容易在 Followers 節(jié)點(diǎn)上提供線(xiàn)性一致讀:
  8. Follower 節(jié)點(diǎn)向 Leader 請(qǐng)求***的 ReadIndex;
  9. Leader 執(zhí)行上面前 3 步的過(guò)程(確定自己真的是 Leader),并返回 ReadIndex 給 Follower;
  10. Follower 等待自己的 applyIndex 超過(guò)了 ReadIndex;
  11. Follower 執(zhí)行 read 請(qǐng)求,將結(jié)果返回給 Client。(SOFAJRaft 中可配置是否從 Follower 讀取,默認(rèn)不打開(kāi))
  12. ReadIndex小結(jié):
  13. 相比較于走 Raft Log 的方式,ReadIndex 省去了磁盤(pán)的開(kāi)銷(xiāo),能大幅度提升吞吐,結(jié)合 SOFAJRaft 的 batch + pipeline ack + 全異步機(jī)制,三副本的情況下 Leader 讀的吞吐可以接近于 RPC 的吞吐上限;
  14. 延遲取決于多數(shù)派中最慢的一個(gè) heartbeat response,理論上對(duì)于降低延時(shí)的效果不會(huì)非常顯著。
  15. Lease Read
  16. Lease Read 與 ReadIndex 類(lèi)似,但更進(jìn)一步,不僅省去了 Log,還省去了網(wǎng)絡(luò)交互。它可以大幅提升讀的吞吐也能顯著降低延時(shí)。
  17. 基本的思路是 Leader 取一個(gè)比 election timeout 小的租期(***小一個(gè)數(shù)量級(jí)),在租約期內(nèi)不會(huì)發(fā)生選舉,這就確保了 Leader 不會(huì)變,所以可以跳過(guò) ReadIndex 的第二步,也就降低了延時(shí)??梢钥吹?Lease Read 的正確性和時(shí)間是掛鉤的,因此時(shí)間的實(shí)現(xiàn)至關(guān)重要,如果時(shí)鐘漂移嚴(yán)重,這套機(jī)制就會(huì)有問(wèn)題。
  18. 實(shí)現(xiàn)方式:
  19. 定時(shí) heartbeat 獲得多數(shù)派響應(yīng),確認(rèn) Leader 的有效性 (在 SOFAJRaft 中默認(rèn)的 heartbeat 間隔是 election timeout 的十分之一);
  20. 在租約有效時(shí)間內(nèi),可以認(rèn)為當(dāng)前 Leader 是 Raft Group 內(nèi)的唯一有效 Leader,可忽略 ReadIndex 中的 heartbeat 確認(rèn)步驟(2);
  21. Leader 等待自己的狀態(tài)機(jī)執(zhí)行,直到 applyIndex 超過(guò)了 ReadIndex,這樣就能夠安全的提供 Linearizable Read 了 。

在 SOFAJRaft 中發(fā)起一次線(xiàn)性一致讀請(qǐng)求的代碼展示:

  1. // KV 存儲(chǔ)實(shí)現(xiàn)線(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.  @Override 
  9.  public void run(Status status, long index, byte[] reqCtx) { 
  10.  if (status.isOk()) { 
  11.  try { 
  12.  // ReadIndexClosure 回調(diào)成功,可以從狀態(tài)機(jī)讀取***數(shù)據(jù)返回 
  13.  // 如果你的狀態(tài)實(shí)現(xiàn)有版本概念,可以根據(jù)傳入的日志 index 編號(hào)做讀取 
  14.  asyncContext.sendResponse(new ValueCommand(fsm.getValue(key))); 
  15.  } catch (KeyNotFoundException e) { 
  16.  asyncContext.sendResponse(GetCommandProcessor.createKeyNotFoundResponse()); 
  17.  } 
  18.  } else { 
  19.  // 特定情況下,比如發(fā)生選舉,該讀請(qǐng)求將失敗 
  20.  asyncContext.sendResponse(new BooleanCommand(false, status.getErrorMsg())); 
  21.  } 
  22.  } 
  23.  }); 

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

  1. Leader 選舉;
  2. 分布式鎖服務(wù),比如 Zookeeper,在 SOFAJRaft 中的 RheaKV 模塊提供了完整的分布式鎖實(shí)現(xiàn);
  3. 高可靠的元信息管理,可直接基于 SOFAJRaft-RheaKV 存儲(chǔ);
  4. 分布式存儲(chǔ)系統(tǒng),如分布式消息隊(duì)列、分布式文件系統(tǒng)、分布式塊系統(tǒng)等等。

使用案例

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

實(shí)踐

一、基于 SOFAJRaft 設(shè)計(jì)一個(gè)簡(jiǎn)單的 KV Store

螞蟻金服開(kāi)源 SOFAJRaft:生產(chǎn)級(jí) Java Raft 算法庫(kù)

二、基于 SOFAJRaft 的 RheaKV 的設(shè)計(jì)

螞蟻金服開(kāi)源 SOFAJRaft:生產(chǎn)級(jí) Java Raft 算法庫(kù)

功能名詞

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è)左閉右開(kāi)的區(qū)間 [startKey, endKey), 可根據(jù)請(qǐng)求流量/負(fù)載/數(shù)據(jù)量大小等指標(biāo)自動(dòng)分裂以及自動(dòng)副本搬遷。

特點(diǎn)

  • 嵌入式
  • 強(qiáng)一致性
  • 自驅(qū)動(dòng)
  • 自診斷, 自?xún)?yōu)化, 自決策

以上幾點(diǎn)(尤其2、3) 基本都是依托于 SOFAJRaft 自身的功能來(lái)實(shí)現(xiàn),詳細(xì)介紹請(qǐng)參考 SOFAJRaft 文檔 。

致謝

感謝 braft、etcd、tikv 貢獻(xiàn)了優(yōu)秀的 Raft 實(shí)現(xiàn),SOFAJRaft 受益良多。

責(zé)任編輯:張燕妮 來(lái)源: 阿里云云棲社區(qū)
相關(guān)推薦

2015-10-15 21:03:04

螞蟻金服

2018-05-17 16:01:00

螞蟻金服金融數(shù)字化轉(zhuǎn)型

2019-05-17 16:13:25

機(jī)器學(xué)習(xí)SQLFlow螞蟻金服

2020-11-10 09:30:48

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

2016-08-31 10:55:30

螞蟻金服前端

2024-03-13 07:35:34

歸因診斷算法KPI 指標(biāo)

2015-10-22 13:15:22

Docker私有云技術(shù)棧

2017-10-16 13:55:53

大數(shù)據(jù)

2018-07-16 16:41:11

螞蟻金服金融科技科技開(kāi)放

2018-05-07 17:15:40

借貸寶

2020-10-15 12:29:49

禁令黑名單螞蟻金服

2021-06-03 15:27:31

RaftSOFAJRaft

2015-11-11 21:41:35

螞蟻金服雙11

2015-10-19 10:07:18

螞蟻金服上市

2018-10-11 11:15:24

2019-10-06 23:57:08

OceanBase螞蟻金服TPC-C

2019-04-22 11:05:54

螞蟻金服面經(jīng)內(nèi)存

2018-08-15 15:16:05

移動(dòng)App

2015-10-16 15:58:37

支付寶刷臉馬云

2022-04-26 09:44:29

算法庫(kù)EasyCV開(kāi)源
點(diǎn)贊
收藏

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