分布式(一致性協議)之領導人選舉( DotNext.Net.Cluster 實現Raft 選舉 )

分布式(一致性協議)之領導人選舉( DotNext.Net.Cluster 實現Raft 選舉 )

繼分布式鎖之后的又一高可用技術爽文之分布式領導選舉 或者說 分布式一致性協議的實現

分布式選舉是實現高可用的必備技術,想實現主從,就必須得有選舉的策略,有主從才會有一個真正的管理端進行資源的協調分配。

首先需要明確的是一致性算法的目標是什么,主要面對的問題是在只使用單個服務器時由于發生錯誤導致數據丟失等事情發生。解決這個問題的思路也很簡單,就是備份,集群,多個服務器,將操作重復到多個機器上就不怕單個機器出錯了。但隨之而來的就是,數據不一致、亂序等問題,一致性算法想要做到的是即使有結點出錯,對外仍是一個完整的可以正常工作的整體。

選舉算法

實現一致性協議(選舉)的主要算法有兩種

  1. 1.?Raft

  2. 2.?Paxos

相當于 Paxos 來講, Raft協議相對來講簡單一點。但是,Raft 實現起來也不是很容易,如果有朋友試圖想去實現可以參考,這個地方

地址 :https://zinglix.xyz/2020/06/25/raft/

我個人也是 簡單的理解了一下。

Raft 是一個非拜占庭的一致性算法,即所有通信是正確的而非偽造的。N 個結點的情況下(N為奇數)可以最多容忍 (N?1)/2個結點故障

為啥需要單獨的選舉算法

我曾經試圖實現一個WEB服務功能,我不能保證這個服務的高可用,我又不想用其他的現有服務,我就想讓服務自己本身能支持高可用。

當時,因為自己認知的問題,并沒有短時間找到一個可用的方案,不過現在有了。

要是當時有,可能就是別樣風景了,不好說。

分布式選舉的大致算法

簡單的來講就是找到一個領頭的,假設有一個leader key,redis里,誰搶到了,誰就是leader,也是可以實現的。這種分布式鎖實現的領導選舉也可以適用于簡單的項目中,并且,支持單個服務主機。

想用分布式選舉算法,機器最少得2臺以上,或者是概念上的兩臺。

Raft中主要有三個角色 Leader(領導人)、Follower (跟隨者)和 Candidate(候選人),當某臺機器成為了領導人,就會成為主要對外對接人,然后把對接的事情同步給下邊的跟隨者或者候選人同步信息。

因為對外只能有一個主服務,起到協調管理的作用。

這樣,就會把相應的指令(日志)分配各個客戶端,起到數據一致性的作用 ,這樣,當領導人廢了,下個人接任,還能繼續起到作用。

Raft 選舉的實例

我找了很多.Net 實現的Raft,很多只能說是個玩具,不能用于生產。

不過幸好,還真有生產級別的。

那就是 DotNext.Net.Cluster 和 DotNext.AspNetCore.Cluster (支持http ) 。

主要是基于 DotNext 中的組件。

DotNext.Net.Cluster 和 DotNext.AspNetCore.Cluster

  1. 1.?DotNext.Net.Cluster包含集群編程模型、Raft 算法的傳輸無關實現、Raft 的 TCP 和 UDP 傳輸綁定、HyParView membersip 協議的傳輸無關實現,用于基于 Gossip 的消息傳遞

  2. 2.?DotNext.AspNetCore.Cluster是基于DotNext.Net.Cluster庫的 Raft 和 HyParView 算法的具體實現,用于構建 ASP.NET Core 應用程序

支持的功能列表

支持的功能列表:

  1. 1. 網絡傳輸:TCP、UDP、HTTP 1.1、HTTP/2、HTTP/3

  2. 2. TLS 支持:TCP、HTTP 1.1、HTTP/2、HTTP/3

  3. 3.?支持日志壓縮的高性能、通用Persistent Write-Ahead Log

  4. 4.?跨集群節點復制日志條目

  5. 5.?與 ASP.NET Core 框架緊密集成

  6. 6.?對 Docker/LXC/Windows 容器友好

  7. 7.?一切都是可擴展的

  • ??7.1 自定義預寫日志

  • ??7.2 自定義網絡傳輸

  • ??7.3 集群成員發現

基于 DotNext.Net.Cluster 的TCP 選舉實例

其實他也是支持http的,當然,更多姿勢,得大佬自己去挖掘了。

項目大致結構

e6b8b32d9afd856a99b06f3bfe0f7e2e.png

細心的小伙伴就會發現,這個是個.Net 6的項目,因為它的nuget包,只支持.Net 6的。

有需要的可以自己改改。

項目是參考源示例,改了一下,有需要的朋友直接去看官方案例

項目重點

Install-Package?DotNext.Net.Cluster?-Version?4.6.0

DataModifier.cs

internal?sealed?class?DataModifier?:?BackgroundService
{private?readonly?IRaftCluster?cluster;private?readonly?ISupplier<long>?valueProvider;public?DataModifier(IRaftCluster?cluster,?ISupplier<long>?provider){this.cluster?=?cluster;valueProvider?=?provider;}protected?override?async?Task?ExecuteAsync(CancellationToken?stoppingToken){while?(!stoppingToken.IsCancellationRequested){await?Task.Delay(1000,?stoppingToken).ConfigureAwait(false);var?leadershipToken?=?cluster.LeadershipToken;TitleInfo.Show(!leadershipToken.IsCancellationRequested);if?(!leadershipToken.IsCancellationRequested){var?newValue?=?valueProvider.Invoke()?+?500L;Console.WriteLine("保存領導節點生成的值?{0}",?newValue);var?source?=?CancellationTokenSource.CreateLinkedTokenSource(stoppingToken,?leadershipToken);try{var?entry?=?new?Int64LogEntry?{?Content?=?newValue,?Term?=?cluster.Term?};await?cluster.ReplicateAsync(entry,?source.Token);}catch?(Exception?e){Console.WriteLine("未知異常?{0}",?e);}finally{source?.Dispose();}}}}
}

這個應該是核心服務,會與其他客戶端進行通信和具體的選舉,以及日志的傳輸

Program.cs

class?Program
{static?async?Task?Main(string[]?args){await?UseTcpTransport(Path.Combine(AppContext.BaseDirectory,?"raftConfig"));}static?Task?UseTcpTransport(string?path){//獲取所有配置var?jsonConfiguration?=?new?ConfigurationBuilder().SetBasePath(Environment.CurrentDirectory).AddJsonFile("appsettings.json",?optional:?true,?reloadOnChange:?true).Build();var?NodeInfo?=?new?NodeInfo();jsonConfiguration.Bind("NodeInfo",?NodeInfo);Console.WriteLine($"MainNode:{NodeInfo.MainNode}");TitleInfo.Node?=?NodeInfo.MainNode;var?configuration?=?new?RaftCluster.TcpConfiguration(IPEndPoint.Parse(NodeInfo.MainNode)){RequestTimeout?=?TimeSpan.FromMilliseconds(140),LowerElectionTimeout?=?150,UpperElectionTimeout?=?300,TransmissionBlockSize?=?4096,ColdStart?=?false,};//加載全部地址//線上環境自己重寫服務var?builder?=?configuration.UseInMemoryConfigurationStorage().CreateActiveConfigurationBuilder();foreach?(var?item?in?NodeInfo.Nodes){var?address?=?IPEndPoint.Parse(item);builder.Add(ClusterMemberId.FromEndPoint(address),?address);}builder.Build();TitleInfo.Show();return?UseConfiguration(configuration,?path);}static?async?Task?UseConfiguration(RaftCluster.NodeConfiguration?config,?string??persistentStorage){var?loggerFactory?=?new?LoggerFactory();var?loggerOptions?=?new?ConsoleLoggerOptions{LogToStandardErrorThreshold?=?LogLevel.Warning};loggerFactory.AddProvider(new?ConsoleLoggerProvider(new?FakeOptionsMonitor<ConsoleLoggerOptions>(loggerOptions)));config.LoggerFactory?=?loggerFactory;using?var?cluster?=?new?RaftCluster(config);cluster.LeaderChanged?+=?ClusterConfigurator.LeaderChanged;var?modifier?=?default(DataModifier?);if?(!string.IsNullOrEmpty(persistentStorage)){var?state?=?new?SimplePersistentState(persistentStorage,?new?AppEventSource());cluster.AuditTrail?=?state;modifier?=?new?DataModifier(cluster,?state);}await?cluster.StartAsync(CancellationToken.None);await?(modifier?.StartAsync(CancellationToken.None)????Task.CompletedTask);//控制臺等待取消using?var?handler?=?new?CancelKeyPressHandler();Console.CancelKeyPress?+=?handler.Handler;await?handler.WaitAsync();Console.CancelKeyPress?-=?handler.Handler;//停止服務await?(modifier?.StopAsync(CancellationToken.None)????Task.CompletedTask);await?cluster.StopAsync(CancellationToken.None);}
}

總體來說,項目還是很簡單的。

我把客戶端的地址給配置了

appsettings.json

這個結構應該很容易理解,一個是當前端的地址,一個是所有節點的地址,當然也包含當前地址。

{"NodeInfo":?{"MainNode":?"127.0.0.1:6001"?,"Nodes":?["127.0.0.1:6001","127.0.0.1:6002","127.0.0.1:6003"]}
}

運行方式

我自己是把Bin目錄復制三份,每份的 appsettings.json 修改下,然后,雙擊 RaftDemo.exe 就運行起來了。

注意

如果起用一個節點沒個卵用,最少得兩個節點。

運行效果

b5243350eacac998f407aaa84b9581c7.gif

總結

這個庫是可以用在生產環境的,所以,還是值得研究一下下的。

代碼地址

https://github.com/kesshei/RaftDemo.git

https://gitee.com/kesshei/RaftDemo.git

參考文檔

https://zinglix.xyz/2020/06/25/raft/

https://github.com/dotnet/dotNext/tree/master/src/cluster

一鍵三連呦!,感謝大佬的支持,您的支持就是我的動力!

堅持更了大概一個月,也有幾個鐵粉了,會持續更,但是連續更太累了(按天更吃不消哦)。

感謝大佬的支持。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/285240.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/285240.shtml
英文地址,請注明出處:http://en.pswp.cn/news/285240.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

投巧解決JavaScript split方法出現空字符的問題

直接使用split&#xff0c;前后各有一個“”值。 >> var str,a,b,c,d,e,f,; >> str.split(,);//(8) ["", "a", "b", "c", "d", "e", "f", ""]臨時方法&#xff1a;split后&…

C語言試題146之反向輸出一個鏈表

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款模擬面試、刷題神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目:反向輸出一個鏈表 2 、溫馨提…

【ArcGIS Pro微課1000例】0006:ArcGIS Pro 2.5三維顯示DEM數字高程模型

通過ArcGIS的學習,我們知道,ArcScene可以實現二維數據的三維顯示,是將二維數據(例如DEM)進行自定義表面浮動拉伸。那么ArcGIS Pro中能不能實現DEM的三維顯示呢? ArcScene三維顯示結果: 目前所采用的ArcGIS Pro 2.5版本還不能直接將DEM進行三維顯示,我們的做法是參照Ar…

中國古代歷朝首都一覽

【五帝時期】&#xff08;約公元前26世紀初—公元前2070年&#xff09; 『黃帝』有熊&#xff08;今河南鄭州新鄭&#xff09; 『顓頊』帝丘&#xff08;今河南濮陽&#xff09; 『帝嚳』帝丘&#xff08;今河南濮陽&#xff09;、西亳&#xff08;今河南洛陽偃師西&#xff09…

程序員的自我修養:有助于提高溝通能力的7本書

直接影響工作效率的四種能力&#xff1a;溝通能力、自學能力、自我管理能力、問題解決能力。提高溝通能力&#xff0c;是程序員提高自我修養的必要條件。相信很多人跟我一樣&#xff0c;性格內向&#xff0c;信仰技術&#xff0c;很少有跟人說話的愿望&#xff0c;只是想看代碼…

玩轉 Linux 之:磁盤分區、掛載知多少?

轉載于&#xff1a;http://my.oschina.net/leejun2005/blog/290073 在做日志機擴容的時候&#xff0c;發現運維同學將一塊硬盤的掛載點沒有同以前的日志機保持一致&#xff0c;考慮到這會給日后的維護帶來麻煩&#xff0c;于是嘗試著手修改&#xff0c;在修改的同時&#xff0c…

C# NanoFramework 點燈和按鍵 之 ESP32

本來周末是要搞個大的&#xff0c;WIFI 和 Web網頁之類的&#xff0c;奈何搞了兩天&#xff0c;并與外國友人聊過后&#xff0c;才發現是固件有問題&#xff0c;晚上與大佬進行交流后才發現&#xff0c;原來ESP32S的官方固件有問題&#xff0c;搞不了。所以&#xff0c;建議買的…

【ArcGIS Pro微課1000例】0002:ArcGIS Pro 2.5二三維聯動顯示

ArcGIS Pro是一款全新的桌面應用程序,它改變了桌面GIS的工作方式,以滿足新一代WebGIS應用模式。ArcGIS Pro采用Ribbon界面風格,給人全新的用戶體驗。它作為一個高級的應用程序,可以對來自本地、ArcGIS Online、或者Portal for ArcGIS的數據進行可視化、編輯、分析。同時,實…

Spring Boot 解決跨域Cors問題

后端主要代碼&#xff1a; &#xff08;http://localhost:8080/ &#xff09; /*WebCorsConfig.java*/ package com.example.demo.Controller;import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsR…

C語言試題147之創建一個鏈表并且排序輸出這個鏈表

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款模擬面試、刷題神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目:創建一個鏈表并且排序輸出這…

DOM節點創建(jQuery)

1DOM創建節點及節點屬性 通過JavaScript可以很方便的獲取DOM節點&#xff0c;從而進行一系列的DOM操作。但實際上一般開發者都習慣性的先定義好HTML結構&#xff0c;但這樣就非常不靈活了。 試想下這樣的情況&#xff1a;如果我們通過AJAX獲取到數據之后然后才能確定結構的話&a…

PHP中刷新輸出緩沖

2019獨角獸企業重金招聘Python工程師標準>>> http://www.cnblogs.com/mutuan/archive/2012/03/18/2404957.html 轉載于:https://my.oschina.net/wuzhencan/blog/652259

2021最新計算機二級C語言試題

一、選擇題 (1) 下面敘述正確的是( C ) A. 算法的執行效率與數據的存儲結構無關 B. 算法的空間復雜度是指算法程序中指令(或語句)的條數 C. 算法的有窮性是指算法必須能在執行有限個步驟之后終止 D. 以上三種描述都不對 (2) 以下數據結構中不屬于線性數據結構的是( C ) A…

[webpack3.8.1]Guides-4-Output Management(輸出管理)

Output Management This guide extends on code examples found in the Asset Management guide.這個指南將在上一個指南的基礎上對示例代碼進行擴展。 So far weve manually included all our assets in our index.html file, but as your application grows and once you sta…

有條件地 [JsonIgnore]

前言通常&#xff0c;在進行 JSON 序列化或反序列化時&#xff0c;如果要忽略某個屬性&#xff0c;我們會使用 [JsonIgnore] 特性&#xff1a;public class User {public int Id { get; set; }[JsonIgnore]public string Name { get; set; } }var user new User { Id 1, Name…

C語言試題145之創建一個鏈表

??個人主頁:個人主頁 ??系列專欄:C語言試題200例 ??推薦一款模擬面試、刷題神器?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 題目:創建一個鏈表 2 、溫馨提示 …

[轉]IntelliJ IDEA 2019.3正式發布,給我們帶來哪些新特性?

每篇一句 工欲善其事必先利其器 ——《論語衛靈公》 前言 千呼萬喚始出來。自從JetBrains在今年7月24日發布了IDEA 2019.2版本后&#xff0c;從9月份開始我便一直在關注此版本正式版的發布。JetBrains公司在9月中旬就對外公布了下一個主要版本 2019.3的Roadmap&#xff0c;而且…

Git中的日常使用 碼云

http://git.mydoc.io/?t83143轉載于:https://www.cnblogs.com/yangyuqiu/p/6164822.html

【譚浩強版】C語言程序設計(第三版)課后習題完整答案附源碼--高等教育出版社

文章目錄 第一章 語言程序設計的概念第二章 基本數據類型第三章 C語言程序的流程控制第四章 模塊化程序設計第五章 數組第六章 指針第一章 語言程序設計的概念 1.1 請編寫一個程序, 顯示以下兩行文字。 #include <stdio.h> main() {printf("I am a student.\n&qu…

php判斷是否為json格式的方法

http://www.poluoluo.com/jzxy/201403/265005.html 首先要記住json_encode返回的是字符串, 而json_decode返回的是對象 判斷數據不是JSON格式: .代碼如下:function is_not_json($str){ return is_null(json_decode($str));}判斷數據是合法的json數據: (PHP版本大于5.3) .代碼如…