欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

SOFAJRaft-RheaKVMULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理

這篇文章主要介紹“SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理”,在日常操作中,相信很多人在SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對(duì)大家解答”SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

創(chuàng)新互聯(lián)公司是一家專業(yè)提供尉犁企業(yè)網(wǎng)站建設(shè),專注與網(wǎng)站制作、成都網(wǎng)站建設(shè)、H5網(wǎng)站設(shè)計(jì)、小程序制作等業(yè)務(wù)。10年已為尉犁眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)絡(luò)公司優(yōu)惠進(jìn)行中。

SOFAStackScalable Open Financial  Architecture Stack 是螞蟻金服自主研發(fā)的金融級(jí)分布式架構(gòu),包含了構(gòu)建金融級(jí)云原生架構(gòu)所需的各個(gè)組件,是在金融場景里錘煉出來的最佳實(shí)踐。

前言

RheaKV 是首個(gè)以 JRaft 為基礎(chǔ)實(shí)現(xiàn)的一個(gè)原生支持分布式的嵌入式鍵值(key、value)數(shù)據(jù)庫,現(xiàn)在本文將從 RheaKV 是如何利用 MULTI-RAFT-GROUP 的方式實(shí)現(xiàn) RheaKV 的高性能及容量的可擴(kuò)展性的,從而進(jìn)行全面的源碼、實(shí)例剖析。

MULTI-RAFT-GROUP

通過對(duì) Raft 協(xié)議的描述我們知道:用戶在對(duì)一組 Raft 系統(tǒng)進(jìn)行更新操作時(shí)必須先經(jīng)過 Leader,再由 Leader 同步給大多數(shù) Follower。而在實(shí)際運(yùn)用中,一組 Raft 的 Leader 往往存在單點(diǎn)的流量瓶頸,流量高便無法承載,同時(shí)每個(gè)節(jié)點(diǎn)都是全量數(shù)據(jù),所以會(huì)受到節(jié)點(diǎn)的存儲(chǔ)限制而導(dǎo)致容量瓶頸,無法擴(kuò)展。

MULTI-RAFT-GROUP 正是通過把整個(gè)數(shù)據(jù)從橫向做切分,分為多個(gè) Region 來解決磁盤瓶頸,然后每個(gè) Region 都對(duì)應(yīng)有獨(dú)立的 Leader 和一個(gè)或多個(gè) Follower 的 Raft 組進(jìn)行橫向擴(kuò)展,此時(shí)系統(tǒng)便有多個(gè)寫入的節(jié)點(diǎn),從而分擔(dān)寫入壓力,圖如下:

SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理cdn.nlark.com/yuque/0/2019/jpeg/325890/1557569369003-7d4762a0-2590-48bc-afc9-b4e53b520054.jpeg">

此時(shí)磁盤及 I/O 瓶頸解決了,那多個(gè) Raft Group 是如何協(xié)作的呢,我們接著往下看。

選舉及復(fù)制

RheaKV 主要由 3 個(gè)角色組成:PlacementDriver(以下成為 PD) 、Store、Region。由于 RheaKV 支持多組 Raft,所以比單組場景多出一個(gè) PD 角色,用來調(diào)度以及收集每個(gè) Store 及 Region 的基礎(chǔ)信息。

SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理

PlacementDriver

PD 負(fù)責(zé)整個(gè)集群的管理調(diào)度、Region ID 生成等。此組件非必須的,如果不使用 PD,設(shè)置 PlacementDriverOptions 的 fake 屬性為 true 即可。PD 一般通過 Region 的心跳返回信息進(jìn)行對(duì) Region 調(diào)度,Region 處理完后,PD 則會(huì)在下一個(gè)心跳返回中收到 Region 的變更信息來更新路由及狀態(tài)表。

Store

通常一個(gè) Node 負(fù)責(zé)一個(gè) Store,Store 可以被看作是 Region 的容器,里面存儲(chǔ)著多個(gè)分片數(shù)據(jù)。Store 會(huì)向 PD 主動(dòng)上報(bào) StoreHeartbeatRequest 心跳,心跳交由 PD 的 handleStoreHeartbeat 處理,里面包含該 Store 的基本信息,比如,包含多少 Region,有哪些 Region 的 Leader  在該 Store 等。

Region

Region 是數(shù)據(jù)存儲(chǔ)、搬遷的最小單元,對(duì)應(yīng)的是 Store 里某個(gè)實(shí)際的數(shù)據(jù)區(qū)間。每個(gè) Region 會(huì)有多個(gè)副本,每個(gè)副本存儲(chǔ)在不同的 Store,一起組成一個(gè)Raft Group。Region 中的 Leader 會(huì)向 PD 主動(dòng)上報(bào) RegionHeartbeatRequest 心跳,交由 PD 的 handleRegionHeartbeat 處理,而 PD 是通過 Region 的 Epoch 感知 Region 是否有變化。

RegionRouteTable 路由表組件

Muti-Raft-Group 的多 Region 是通過 RegionRouteTable 路由表組件進(jìn)行管理的,可通過 addOrUpdateRegion、removeRegion 進(jìn)行添加、更新、移除 Region,也包括 Region 的拆分。目前暫時(shí)還未實(shí)現(xiàn) Region 的聚合,后面會(huì)考慮實(shí)現(xiàn)。

分區(qū)邏輯與算法 Shard

SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理

“讓每組 Raft 負(fù)責(zé)一部分?jǐn)?shù)據(jù)。”

數(shù)據(jù)分區(qū)或者分片算法通常就是 Range 和 Hash,RheaKV 是通過 Range 進(jìn)行數(shù)據(jù)分片的,分成一個(gè)個(gè) Raft Group,也稱為 Region。這里為何要設(shè)計(jì)成 Range 呢?原因是 Range 切分是按照對(duì) Key 進(jìn)行字節(jié)排序后再做每段每段切分,像類似 scan 等操作對(duì)相近 key 的查詢會(huì)盡可能集中在某個(gè) Region,這個(gè)是 Hash 無法支持的,就算遇到單個(gè) Region 的拆分也會(huì)更好處理一些,只用修改部分元數(shù)據(jù),不會(huì)涉及到大范圍的數(shù)據(jù)挪動(dòng)。

當(dāng)然 Range 也會(huì)有一個(gè)問題那就是,可能會(huì)存在某個(gè) Region 被頻繁操作成為熱點(diǎn) Region。不過也有一些優(yōu)化方案,比如 PD 調(diào)度熱點(diǎn) Region 到更空閑的機(jī)器上,或者提供 Follower 分擔(dān)讀的壓力等。

Region 和 RegionEpoch 結(jié)構(gòu)如下:

class Region {
		long              id;            // region id
    // Region key range [startKey, endKey)
		byte[]            startKey;      // inclusive
		byte[]            endKey;        // exclusive
		RegionEpoch       regionEpoch;   // region term
		List<Peer>        peers;         // all peers in the region
}
class RegionEpoch {
		// Conf change version, auto increment when add or remove peer
  	long              confVer;
  	// Region version, auto increment when split or merge
  	long              version;
}
class Peer {
		long              id;
    long              storeId;
    Endpoint          endpoint;
}

Region.id:為 Region 的唯一標(biāo)識(shí),通過 PD 全局唯一分配。

Region.startKey、Region.endKey:這個(gè)表示的是 Region 的 key 的區(qū)間范圍 [startKey, endKey),特別值得注意的是針對(duì)最開始 Region 的 startKey,和最后 Region 的 endKey 都為空。

Region.regionEpoch:當(dāng) Region 添加和刪除 Peer,或者 split 等,此時(shí) regionEpoch 就會(huì)發(fā)生變化,其中 confVer 會(huì)在配置修改后遞增,version 則是每次有 split 、merge(還未實(shí)現(xiàn))等操作時(shí)遞增。

Region.peers:peers 則指的是當(dāng)前 Region 所包含的節(jié)點(diǎn)信息,Peer.id 也是由 PD 全局分配的,Peer.storeId 代表的是 Peer 當(dāng)前所處的 Store。

讀與寫 Read / Write

由于數(shù)據(jù)被拆分到不同 Region 上,所以在進(jìn)行多 key 的讀、寫、更新操作時(shí)需要操作多個(gè) Region,這時(shí)操作前我們需要得到具體的 Region,然后再單獨(dú)對(duì)不同 Region 進(jìn)行操作。我們以在多 Region上 scan 操作為例, 目標(biāo)是返回某個(gè) key 區(qū)間的所有數(shù)據(jù): 

  1. 我們首先看 scan 方法的核心調(diào)用方法 internalScan 的異步實(shí)現(xiàn):

例如:com.alipay.sofa.jraft.rhea.client.DefaultRheaKVStore#scan(byte[], byte[], boolean, boolean)

SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理

我們很容易看到,在調(diào)用 scan 首先讓 PD Client 通過 RegionRouteTable.findRegionsByKeyRange 檢索 startKey、endKey 所覆蓋的 Region,最后返回的可能為多個(gè) Region,具體 Region 覆蓋檢索方法如下:

SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理

檢索相關(guān)變量定義如下:

SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理

我們可以看到整個(gè) RheaKV 的 range 路由表是通過 TreeMap 的進(jìn)行存儲(chǔ)的,正呼應(yīng)我們前面講過所有的 key 是通過對(duì)應(yīng)字節(jié)進(jìn)行排序存儲(chǔ)。對(duì)應(yīng)的 Value 為該 Region 的 RegionId,隨后我們通過 Region 路由 regionTable 查出即可。

現(xiàn)在我們得到 scan 覆蓋到的所有 Region:List<Region> 在循環(huán)查詢中我們看到有一個(gè)“retryCause -> {}”的 Lambda 表達(dá)式很容易看出這里是加持異常重試處理,后面我們會(huì)講到,接下來會(huì)通過 internalRegionScan 查詢每個(gè) Region 的結(jié)果。具體源碼如下:

SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理

這里也同樣有一個(gè)重試處理,可以看到代碼中根據(jù)當(dāng)前是否為 Region 節(jié)點(diǎn)來決定是本機(jī)查詢還是通過RPC進(jìn)行查詢,如果是本機(jī)則調(diào)用 rawKVStore.scan() 進(jìn)行本地直接查詢,反之通過 rheaKVRpcService 進(jìn)行 RPC 遠(yuǎn)程節(jié)點(diǎn)查詢。最后每個(gè) Region 查詢都返回為一個(gè) future,通過 FutureHelper.joinList 工具類 CompletableFuture.allOf 異步并發(fā)返回結(jié)果 List<KVEntry>

  1. 我們再看看寫入具體流程。相比 scan 讀,put 寫相對(duì)比較簡單,只需要針對(duì) key 計(jì)算出對(duì)應(yīng) Region 再進(jìn)行存儲(chǔ)即可,我們可以看一個(gè)異步 put 的例子。

例如:com.alipay.sofa.jraft.rhea.client.DefaultRheaKVStore#put(java.lang.String, byte[])

SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理

我們可以發(fā)現(xiàn) put 基礎(chǔ)方法是支持 batch 的,即可成批提交。如未使用 batch 即直接提交,具體邏輯如下:

SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理

通過 pdClinet 查詢對(duì)應(yīng)存儲(chǔ)的 Region,并且通過 regionId 拿到 RegionEngine,再通過對(duì)應(yīng)存儲(chǔ)引擎 KVStore 進(jìn)行 put,整個(gè)過程同樣支持重試機(jī)制。我們再回過去看看 batch 的實(shí)現(xiàn),很容易發(fā)現(xiàn)利用到了 Disruptor 的 RingBuffer 環(huán)形緩沖區(qū),無鎖隊(duì)列為性能提供了保障,代碼現(xiàn)場如下:

SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理

Split / Merge

  1. 什么時(shí)候 Region 會(huì)拆分?

前面我們有講過,PD 會(huì)在 Region 的 heartBeat 里面對(duì) Region 進(jìn)行調(diào)度,當(dāng)某個(gè) Region 里的 keys 數(shù)量超過預(yù)設(shè)閥值,我們即可對(duì)該 Region 進(jìn)行拆分,Store 的狀態(tài)機(jī) KVStoreStateMachine 即收到拆分消息進(jìn)行拆分處理。具體拆分源碼如下:

KVStoreStateMachine.doSplit 源碼如下:

SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理

StoreEngine.doSplit 源碼如下:

SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理

我們可以輕易的看到從原始 parentRegion 切分成 region 和 pRegion,并重設(shè)了 startKey、endKey 和版本號(hào),并添加到 RegionEngineTable 注冊到 RegionKVService,同時(shí)調(diào)用 pdClient.getRegionRouteTable().splitRegion() 方法進(jìn)行更新存儲(chǔ)在 PD 的 Region 路由表。

  1. 什么時(shí)候需要對(duì) Region 進(jìn)行合并?

既然數(shù)據(jù)過多需要進(jìn)行拆分,那 Region 進(jìn)行合并那就肯定是 2 個(gè)或者多個(gè)連續(xù)的 Region 數(shù)據(jù)量明顯小于絕大多數(shù) Region 容量則我們可以對(duì)其進(jìn)行合并。這一塊后面會(huì)考慮實(shí)現(xiàn)。

RegionKVService 結(jié)構(gòu)及實(shí)現(xiàn)分析

StoreEngine

通過上面我們知道,一個(gè) Store 即為一個(gè)節(jié)點(diǎn),里面包含著一個(gè)或者多個(gè) RegionEngine,一個(gè) StoreEngine 通常通過 PlacementDriverClient 對(duì) PD 進(jìn)行調(diào)用,同時(shí)擁有 StoreEngineOptions 配置項(xiàng),里面配置著存儲(chǔ)引擎和節(jié)點(diǎn)相關(guān)配置。

  1. 我們以默認(rèn)的 DefaultRheaKVStore 加載 StoreEngine 為例,DefaultRheaKVStore 實(shí)現(xiàn)了 RheaKVStore 接口的基礎(chǔ)功能,從最開始 init 方法,根據(jù) RheaKVStoreOptions 加載了 pdClinet 實(shí)例,隨后加載 storeEngine。

  2. 在 StoreEngine 啟動(dòng)的時(shí)候,首先會(huì)去加載對(duì)應(yīng)的 StoreEngineOptions 配置,構(gòu)建對(duì)應(yīng)的 Store 配置,并且生成一致性讀的線程池 readIndexExecutor、快照線程池 snapshotExecutor、RPC 的線程池 cliRpcExecutor、Raft 的 RPC 線程池 raftRpcExecutor,以及存儲(chǔ) RPC 線程池 kvRpcExecutor、心跳發(fā)送器 HeartbeatSender 等,如果打開代碼,我們還能看到 metricsReportPeriod,打開配置可以進(jìn)行性能指標(biāo)監(jiān)控。

  3. 在 DefaultRheaKVStore 加載完所有工序之后,便可使用 get、set、scan 等操作,還包含對(duì)應(yīng)同步、異步操作。

在這個(gè)過程中里面的 StoreEngine 會(huì)記錄著 regionKVServiceTable、regionEngineTable,它們分別掌握著具體每個(gè)不同的 Region 存儲(chǔ)的操作功能,對(duì)應(yīng)的 key 即為 RegionId。

RegionEngine

每個(gè)在 Store 里的 Region 副本中,RegionEngine 則是一個(gè)執(zhí)行單元。它里面記錄著關(guān)聯(lián)著的 StoreEngine 信息以及對(duì)應(yīng)的 Region 信息。由于它也是一個(gè)選舉節(jié)點(diǎn),所以也包含著對(duì)應(yīng)狀態(tài)機(jī) KVStoreStateMachine,以及對(duì)應(yīng)的 RaftGroupService,并啟動(dòng)里面的 RpcServer 進(jìn)行選舉同步。

這個(gè)里面有個(gè)transferLeadershipTo方法,這個(gè)可被調(diào)用用于平衡當(dāng)前節(jié)點(diǎn)分區(qū)的Leader,避免壓力重疊。

DefaultRegionKVService 是 RegionKVService 的默認(rèn)實(shí)現(xiàn)類,主要處理對(duì) Region 的具體操作。

RheaKV FailoverClosure 解讀

需要特別講到的是,在具體的 RheaKV 操作時(shí),F(xiàn)ailoverClosure 擔(dān)任著比較重要的角色,也給整個(gè)系統(tǒng)增加了一定的容錯(cuò)性。假如在一次 scan 操作中,如果跨 Store 需要多節(jié)點(diǎn) scan 數(shù)據(jù)的時(shí)候,任何網(wǎng)絡(luò)抖動(dòng)都會(huì)造成數(shù)據(jù)不完整或者失敗情況,所以允許一定次數(shù)的重試有利于提高系統(tǒng)的可用性,但是重試次數(shù)不宜過高,如果出現(xiàn)網(wǎng)絡(luò)堵塞,多次 timeout 級(jí)別失敗會(huì)給系統(tǒng)帶來額外的壓力。這里只需要在 DefaultRheaKVStore 中,進(jìn)行配置 failoverRetries 設(shè)置次數(shù)即可。

RheaKV PD 之 PlacementDriverClient 

PlacementDriverClient 接口主要由 AbstractPlacementDriverClient 實(shí)現(xiàn),然后 FakePlacementDriverClient、RemotePlacementDriverClient 為主要功能。FakePlacementDriverClient 是當(dāng)系統(tǒng)不需要 PD 的時(shí)候進(jìn)行 PD 對(duì)象的模擬,這里主要講到 RemotePlacementDriverClient。

  1. RemotePlacementDriverClient 通過PlacementDriverOptions 進(jìn)行加載,并根據(jù)基礎(chǔ)配置刷新路由表;

  2. RemotePlacementDriverClient 承擔(dān)著對(duì)路由表RegionRouteTable 的管控,例如獲取Store、路由、Leader節(jié)點(diǎn)信息等;

  3. RemotePlacementDriverClient 還包含著 CliService,通過 CliService 外部可對(duì)復(fù)制節(jié)點(diǎn)進(jìn)行操作運(yùn)維,如addReplica、removeReplica、transferLeader。

總結(jié)

由于很多傳統(tǒng)存儲(chǔ)中間件并不原生支持分布式,所以一直少有體感,Raft 協(xié)議是一套比較比較好理解的共識(shí)協(xié)議,SOFAJRaft 通俗易懂是一個(gè)非常好的代碼和工程范例,同時(shí) RheaKV 也是一套非常輕量化支持多存儲(chǔ)結(jié)構(gòu)可分片的嵌入式數(shù)據(jù)庫。寫一篇代碼分析文章也是一個(gè)學(xué)習(xí)和進(jìn)步的過程,由此我們也可以窺探到了一些數(shù)據(jù)庫的基礎(chǔ)實(shí)現(xiàn),祝愿社區(qū)能在 SOFAJRaft / RheaKV 基礎(chǔ)上構(gòu)建更加靈活和自治理的系統(tǒng)和應(yīng)用。

到此,關(guān)于“SOFAJRaft-RheaKV MULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

本文名稱:SOFAJRaft-RheaKVMULTI-RAFT-GROUP實(shí)現(xiàn)分析SOFAJRaft的實(shí)現(xiàn)原理
網(wǎng)頁地址:http://chinadenli.net/article36/gdjhsg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站收錄關(guān)鍵詞優(yōu)化網(wǎng)站維護(hù)網(wǎng)站內(nèi)鏈虛擬主機(jī)定制網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)