分布式(一致性协议)之领导人选举( 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.mzph.cn/news/285240.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

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…

程序员的自我修养:有助于提高沟通能力的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的数据进行可视化、编辑、分析。同时,实…

C语言试题147之创建一个链表并且排序输出这个链表

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目:创建一个链表并且排序输出这…

PHP中刷新输出缓冲

2019独角兽企业重金招聘Python工程师标准>>> http://www.cnblogs.com/mutuan/archive/2012/03/18/2404957.html 转载于:https://my.oschina.net/wuzhencan/blog/652259

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;而且…

FineReport中以jws方式调用WebService数据源方案

在使用WebService作为项目的数据源时&#xff0c;希望报表中也是直接调用这个WebService数据源&#xff0c;而不是定义数据连接调用对应的数据库表&#xff0c;这样要怎么实现呢&#xff1f; 在程序中访问WebService应用服务&#xff0c;将WebService返回的数据转为程序数据集&…

C语言试题148之海滩上有一堆桃子,五只猴子来分。第一只猴子把这堆桃子凭据分为五份,多了一个,这只 猴子把多的一个扔入海中,拿走了一份。第二只猴子把剩下的桃子又平均分成五份,又多了 一个,它同样把多的

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目:海滩上有一堆桃子,五只猴子…

一文读懂什么是CTO、技术VP、技术总监、首席架构师

究竟什么是CTO&#xff0c;一个公司真的需要CTO么&#xff1f;哪些公司的职位对于技术管理者来讲真的是CTO的职位&#xff1f;同样是技术最高负责人&#xff0c;为什么有人叫CTO、有人叫技术总监、技术VP&#xff0c;有人叫首席架构师&#xff1f;他们之间的差别是什么&#xf…

与MySQL传统复制相比,GTID有哪些独特的复制姿势?

与MySQL传统复制相比&#xff0c;GTID有哪些独特的复制姿势? http://mp.weixin.qq.com/s/IF1Pld-wGW0q2NiBjMXwfg 陈华军&#xff0c;苏宁云商IT总部资深技术经理&#xff0c;从事数据库服务相关的开发和维护工作&#xff0c;之前曾长期从事富士通关系数据库的开发&#xff0c…

【ArcGIS Pro微课1000例】0007:ArcGIS Pro 2.5质量检查:拓扑创建与编辑案例教程

文章目录 1. 加载矢量数据2. 创建数据库、要素数据集3. 拓扑创建4. 拓扑错误编辑与修改1. 加载矢量数据 矢量数据可以是单独shp格式的文件数据,也可是存在于数据库中的要素类。 2. 创建数据库、要素数据集 创建数据库 无论是在ArcMap,还是ArcGIS Pro中,创建拓扑都需要在…

C语言试题149之809乘以??=800乘以??+9乘以??+1 其中??代表的两位数,8乘以??的结果为两位数,9乘以??的结果为 3 位数。求??代表 的两位数,及 809乘以??后的结果

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目:809*??=800*??+9*??+1…

.Net之时间轮算法(终极版)定时任务

TimeWheelDemo一个基于时间轮原理的定时任务对时间轮的理解其实我是有一篇文章(.Net 之时间轮算法(终极版)[1])针对时间轮的理论理解的&#xff0c;但是&#xff0c;我想&#xff0c;为啥我看完时间轮原理后&#xff0c;会采用这样的方式去实现。可能只是一些小技巧不上大雅之堂…

phpstorm config include paths for swoole

配置phpstorm 当你写swoole 类或者函数时会自动补全 https://github.com/swoole/ide-helper.git 克隆下这个工具包 点加&#xff0c;然后指定你下载好的工具包路径&#xff0c;点ok 本文转自 skinglzw 51CTO博客&#xff0c;原文链接&#xff1a;http://blog.51cto.com/sking…

C语言试题150之八进制转换为十进制

📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 题目:八进制转换为十进制 2 、温馨…

【ArcGIS风暴】ArcGIS创建栅格数据集色彩映射表案例--以GlobeLand30土地覆盖数据为例

矢量数据快速符号化&#xff0c;可以将常用的样式保存到样式符号库&#xff0c;栅格数据快速符号化&#xff0c;需要创建色彩映射表。本文以GlobeLand30土地覆盖数据为例&#xff0c;详解ArcGIS中创建与使用色彩映射表。 文章目录一、 ArcGIS色彩映射表介绍二、土地覆盖数据色彩…