【主流分布式算法总结】

文章目录

  • 分布式常见的问题
  • 常见的分布式算法
    • Raft算法
      • 概念
      • Raft的实现
    • ZAB算法
    • Paxos算法

分布式常见的问题

分布式场景下困扰我们的3个核心问题(CAP):一致性、可用性、分区容错性。
1、一致性(Consistency):无论服务如何拆分,所有实例节点同一时间看到是相同的数据
2、可用性(Availability):不管是否成功,确保每一个请求都能接收到响应
3、分区容错性(Partition Tolerance):系统任意分区后,在网络故障时,仍能操作
在这里插入图片描述
而我们的业务中,一般一致性、可用性、分区容错性,三个满足两个,一般算法就是以CA和AP两个选择性,进行选择。

常见的分布式算法

Raft算法

概念

RAFT(Replicated State Machine Approach)算法是一种一致性分布式复制协议,用于在分布式系统中维护一组服务节点的一致状态。它是一种领导者选举算法,适用于解决分布式系统中的数据复制和一致性问题。
1.领导者选举:RAFT将系统中的节点分为三种角色:领导者(leader)、跟随者(follower)和候选者(candidate)。在任何给定的时刻,系统中都只有一个领导者。节点之间通过选举机制选出领导者,领导者负责处理客户端请求,并在系统中推动状态变更。
跟随者(Follower)
Fllower是所有节点的初始状态,内部都会有一个随机超时时间。这个超时时间,规定了在倒计时结束后仍然收不到Leader的心跳,Follower就会转变为Candidate。
候选者(candidate)
Follower在转变为Candidate后,超时时间重置,倒计时结束时就会向其他节点提名自己的实,拉取选票。
如果能获得半数以上(1/2以上,包含自己投给自己的)的选票,则当选为Leader,这个过程就叫做Leader选举。
所以节点最好是单数,避免极端情况下出现一个集群选举出两个Leader的脑裂问题。
领导者(leader)
Raft集群通过Leader与客户端进行交互,Leader不断处理写请求与发送心跳给Follower,Follower在收到Leader的心跳后,其超时时间会重置,即重新开始倒计时。
正常工作期间只有 Leader 和 Follower,且Leader至多只能有一个。
2.任期(Term):系统中的时间被分为一个个任期。每个任期都有一个唯一的标识符,领导者选举是基于这个任期进行的。当一个候选者成为领导者时,它会增加当前任期的编号,并在该任期内保持领导者身份。
3.日志(Log):RAFT将系统状态的变化表示为一系列日志条目。每个日志条目包含一个命令和任期号。这些日志条目按顺序附加到每个节点的日志中,并通过领导者复制到其他节点。
4.选举过程:当没有领导者时,节点会进入选举过程。在选举过程中,节点变为候选者状态,并向其他节点发送选举请求。候选者获得多数票后成为领导者。为了避免竞争和分裂投票,选举中使用随机化的超时机制。
5.日志复制:领导者负责将新的日志条目复制到其他节点。一旦大多数节点确认了日志条目,领导者就可以提交日志,并通知其他节点将其应用到状态机中。
6.安全性和一致性:RAFT确保在系统中只有一个领导者,并且所有节点都按相同的顺序应用相同的日志条目,从而确保了系统的一致性和安全性。

Raft的实现

public class Node {private int nodeId;private RaftNode raftNode;public Node(int nodeId, RaftNode raftNode) {this.nodeId = nodeId;this.raftNode = raftNode;}public int getNodeId() {return nodeId;}public RaftNode getRaftNode() {return raftNode;}
}
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.*;public class RaftNode implements Runnable {private int nodeId;private List<Node> cluster;private String state;private int currentTerm;private Integer votedFor;private List<String> log;private int commitIndex;private int lastApplied;private Map<Integer, Integer> nextIndex;private Map<Integer, Integer> matchIndex;private Integer leaderId;private final Lock lock;public RaftNode(int nodeId, List<Node> cluster) {this.nodeId = nodeId;this.cluster = cluster;this.state = "Follower";this.currentTerm = 0;this.votedFor = null;this.log = new ArrayList<>();this.commitIndex = 0;this.lastApplied = 0;this.nextIndex = new ConcurrentHashMap<>();this.matchIndex = new ConcurrentHashMap<>();this.leaderId = null;this.lock = new ReentrantLock();}public void start() {new Thread(this).start();}@Overridepublic void run() {while (true) {switch (state) {case "Follower":runFollower();break;case "Candidate":runCandidate();break;case "Leader":runLeader();break;}}}private void runFollower() {long timeout = (long) (150 + Math.random() * 150);long lastHeartbeat = System.currentTimeMillis();while ("Follower".equals(state)) {if (System.currentTimeMillis() - lastHeartbeat >= timeout) {state = "Candidate";return;}try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}}}private void runCandidate() {currentTerm++;votedFor = nodeId;int votesReceived = 1;for (Node peer : cluster) {if (peer.getNodeId() != nodeId && sendRequestVote(peer.getRaftNode())) {votesReceived++;}}if (votesReceived > cluster.size() / 2) {state = "Leader";leaderId = nodeId;for (Node peer : cluster) {if (peer.getNodeId() != nodeId) {nextIndex.put(peer.getNodeId(), log.size());matchIndex.put(peer.getNodeId(), 0);}}} else {state = "Follower";}}private void runLeader() {while ("Leader".equals(state)) {sendHeartbeats();try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}}}private boolean sendRequestVote(RaftNode peer) {peer.lock.lock();try {if (peer.currentTerm <= currentTerm && (peer.votedFor == null || peer.votedFor == nodeId)) {peer.votedFor = nodeId;return true;}} finally {peer.lock.unlock();}return false;}private void sendHeartbeats() {for (Node peer : cluster) {if (peer.getNodeId() != nodeId) {sendAppendEntries(peer.getRaftNode());}}}private void sendAppendEntries(RaftNode peer) {peer.lock.lock();try {if (peer.currentTerm > currentTerm) {state = "Follower";}} finally {peer.lock.unlock();}}
}
import java.util.*;public class RaftCluster {public static void main(String[] args) {List<Node> cluster = new ArrayList<>();for (int i = 0; i < 5; i++) {RaftNode raftNode = new RaftNode(i, cluster);Node node = new Node(i, raftNode);cluster.add(node);raftNode.start();}}
}

ZAB算法

ZAB(ZooKeeper Atomic Broadcast)算法是分布式系统中用来实现一致性的重要协议。它是Apache ZooKeeper分布式协调服务的核心组件,确保集群中的所有节点在数据上的一致性。以下是对ZAB算法的详细解释。

  1. 目标
    ZAB的主要目标:
    顺序一致性:确保所有事务在所有ZooKeeper服务器上以相同的顺序被应用。
    原子广播:确保每个事务被可靠地传递到集群中的所有节点。
    容错性:在部分节点故障的情况下,仍能保证系统的正确性和可用性。
  2. 工作模式
    ZAB算法有两种主要的工作模式:
    广播模式(Broadcast mode):用于正常操作期间处理客户端请求。
    恢复模式(Recovery mode):用于集群启动或领导者故障后,选举新领导者并同步状态。
  3. 广播模式
    在广播模式下,ZAB的工作流程如下:
    领导者选举:集群启动或领导者故障后,会进行领导者选举。新领导者负责处理客户端请求并广播事务。
    事务处理:
    客户端请求被发送到领导者。
    领导者生成提案(Proposal),将提案广播给所有追随者(Follower)。
    追随者接收提案并将其写入事务日志,然后发送确认(ACK)给领导者。
    当领导者收到大多数追随者的确认后,认为提案已提交(Commit),并将提交信息广播给所有追随者。
    每个节点应用提交的事务到其状态机。
  4. 恢复模式
    在恢复模式下,ZAB的工作流程如下:
    数据同步:确保新领导者和追随者之间的数据一致性。追随者将与领导者进行数据同步,获取最新的事务日志。
    领导者选举:如果没有现任领导者,集群会通过投票机制选举出新的领导者。
    状态同步:新领导者与追随者同步状态,以便进入广播模式继续处理客户端请求。
  5. 容错处理
    ZAB通过以下机制实现容错:
    复制日志:每个事务都被写入多个节点的事务日志,确保在部分节点故障时仍然可以恢复数据。
    多数派确认:事务在大多数节点确认后才被提交,保证系统在多数节点可用的情况下仍然一致。
    持久化存储:事务日志被持久化存储在磁盘上,防止数据因节点重启或崩溃而丢失。

Paxos算法

Paxos是一种广泛使用的分布式一致性算法,由计算机科学家Leslie Lamport提出。它用于在分布式系统中达成一致性,即使某些节点发生故障也能保证系统的一致性。Paxos算法的核心思想是在分布式环境中,通过一系列的消息传递和投票机制,确保多个节点对某个值达成共识。
Paxos算法的基本概念
Paxos算法涉及三个主要角色:
提议者(Proposer):提出提案并争取达成共识。
接受者(Acceptor):对提议者提出的提案进行投票。
学习者(Learner):一旦共识达成,学习最终达成的值。
Paxos算法的基本过程
Paxos算法通常分为两个主要阶段:准备阶段(Prepare Phase)和接受阶段(Accept Phase)。

  1. 准备阶段(Prepare Phase)
    提议者选择一个提案编号n并向大多数接受者发送Prepare(n)请求。
    接受者收到Prepare(n)请求后,如果n大于它已经响应过的所有Prepare请求的编号,则接受该请求,并承诺不再接受编号小于n的提案。同时,接受者会向提议者回复它已经接受的提案中编号最大的提案。
  2. 接受阶段(Accept Phase)
    提议者在收到大多数接受者对Prepare(n)请求的响应后,可以确定一个提案值。如果接受者返回了已经接受的提案,提议者会选取编号最大的那个提案值;否则,可以选择任意值。
    提议者将提案(n, value)发送给大多数接受者,请求他们接受该提案。
    接受者收到提案后,如果提案编号n不小于它已经响应过的所有Prepare请求的编号,则接受该提案,并向提议者回复确认消息。
    达成共识
    当提议者收到大多数接受者对Accept(n, value)请求的确认时,认为提案已经被接受,达成共识。
    学习者通过接受者的消息获知已经达成共识的值。
    Paxos算法的特点
    容错性:Paxos算法能够容忍少量的节点故障,只要大多数节点正常工作,系统就能达成一致性。
    一致性:Paxos算法保证所有参与节点最终会达成一致的决策。
    复杂性:Paxos算法的实现和理解相对复杂,特别是在处理边界情况和优化性能时。
    Paxos的变种
    Paxos算法有许多变种,用于在不同的应用场景中优化性能和简化实现,例如:
    Multi-Paxos:扩展Paxos算法以支持多个提案的连续达成共识,常用于实现分布式日志。
    Fast Paxos:通过减少消息传递的轮数来加速达成共识。
    Cheap Paxos:优化资源使用,降低实现成本。
    应用场景
    Paxos算法广泛应用于需要分布式一致性的系统中,例如分布式数据库、分布式文件系统和分布式协调服务等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/341810.html

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

相关文章

Linux 磁盘分区步骤

1.lsblk用于查看磁盘分区情况&#xff0c;lsblk -f用于查看uuid字符串以及挂载点。 以下是虚拟机部分添加磁盘的步骤。 其余没展示的都按照默认设置进入下一步即可。 2.添加完成后使用reboot重新进入后再使用lsblk就会发现磁盘sdb已经有了&#xff0c;但是没有分区。现在添加分…

现代控制中可控性的Gramian判据

知乎三角猫frank对于这块内容写的非常好&#xff0c;但这个输入的构造还是很难过于没头没尾 数学好的人&#xff0c;可能看一眼根据形式就能推出gramian的构造&#xff0c;但对我这种比较钻牛角尖的人&#xff0c;我就想有一个逻辑链条——gramian是怎么被构造出来的&#xff1…

FreeBSD原生虚拟化Jail的管理软件比较

当前流行的虚拟化技术&#xff0c;除了VMWare、VirtualBox等重型虚拟机&#xff0c;Docker等中型虚拟机外&#xff0c;还有jail等轻型虚拟机解决方案。 jail的简介 Jail最早在FreeBSD 4.X便可使用&#xff0c;并且一直在持续强化它的功能、效率、稳定性以及安全性。 Jail建立…

node mysql的增删改查基础

学习koa时&#xff0c;不选择mongodb&#xff0c;而是MySQL&#xff0c;虽然node对mongodb更亲和&#xff0c;但是我感觉MySQL的键值对的储存结构更正规 1.首选确认你的数据库有个库。有个表,我的如下 2.配置 let mySqlConfig{host:localhost,user:root,password:123456,data…

VS2022,lib调用dll工程的一个函数

lib工程本身是一个静态库工程&#xff0c;没有链接器设置。然而&#xff0c;我们依然可以在lib工程中调用DLL工程中的函数&#xff0c;只需要确保头文件正确导入&#xff0c;并在最终使用lib的可执行文件项目中正确链接DLL的.lib文件。下面是一个详细的步骤说明&#xff1a; 假…

基于Keil5移植LVGL,懂得原理之后什么开发板都可以移植

今天我们来移植一下LVGL&#xff0c;其实LVGL和Qt差不多&#xff0c;操作起来都很简单&#xff0c;看着官方文档都可以自己学习使用。 难就难在移植上面&#xff0c;移植个LVGL花了我三天才弄明白&#xff08;虽然最后发现在一个很弱智的问题上耽误了我两天&#xff09;&#…

AI大模型时代必须关注的数据库 DuckDB1.0 正式发布

开源数据库DuckDB1.0 经过内部6年的打磨&#xff0c;积累了30万行代码&#xff0c;1.8万star&#xff0c;2024.06.03号正式发布了1.0版本&#xff08;代号 Snow Duck&#xff09;。 我们新一代程序员&#xff0c;没能见证MySQL 1.0、PostgreSQL 1.0、Windows 1.0、Linux 1.0、…

HTML跳动的爱心

目录 写在前面 HTML简介 程序设计 修改文字 推荐系列 写在后面 写在前面 本期小编给大家分享可以写字的html动态爱心代码&#xff0c;一起来看看叭~ HTML简介 HTML&#xff08;HyperText Markup Language&#xff09;是一种用于创建网页的标记语言。它是互联网的基础&…

Etcd Raft架构设计和源码剖析1:宏观架构

Etcd Raft架构设计和源码剖析1&#xff1a;宏观架构 | Go语言充电站 序言 Etcd提供了一个样例contrib/raftexample&#xff0c;用来展示如何使用etcd raft。这篇文章通过raftexample介绍如何使用etcd raft。 raft服务 raftexample是一个分布式KV数据库&#xff0c;客户端可…

三十六、openlayers官网示例Earthquake Clusters解析——在聚合图层鼠标触摸显示五角星

官网demo地址&#xff1a; Earthquake Clusters 这篇展示了鼠标触摸聚合图层点位显示五角星的效果。 首先是初始化地图&#xff0c;加载了一个KML格式的矢量数据源&#xff0c;extractStyles为false表示不从kml数据源中提取样式。使用Select添加了鼠标选中的交互事件 vector …

《微服务大揭秘:SpringBoot与SpringCloud的魔法组合》

加入我们的探险队伍&#xff0c;一起深入SpringBoot与SpringCloud构建的微服务世界。以轻松幽默的笔触&#xff0c;带你一步步揭开微服务架构的神秘面纱&#xff0c;从服务发现的智能地图Eureka&#xff0c;到API网关Zuul的城市门卫&#xff0c;每一个环节都充满了惊喜。不仅如…

htb_solarlab

端口扫描 80,445 子域名扫描 木有 尝试使用smbclient连接445端口 Documents目录可查看 将Documents底下的文件下载到本地看看 xlsx文件里有一大串用户信息&#xff0c;包括username和password 先弄下来 不知道在哪登录&#xff0c;也没有子域名&#xff0c;于是返回进行全端…

chat4-Server端保存聊天消息到mysql

本文档描述了Server端接收到Client的消息并转发给所有客户端或私发给某个客户端 同时将聊天消息保存到mysql 服务端为当前客户端创建一个线程&#xff0c;此线程接收当前客户端的消息并转发给所有客户端或私发给某个客户端同时将聊天消息保存到mysql 本文档主要总结了将聊天…

UnityAPI学习之游戏物体的方法使用

目录 游戏物体 创建游戏物体的三种方式 组建的获取和查找 游戏物体的方法与其他成员变量 游戏物体的生成 游戏物体的激活状态/标签(tag)/层级(layer) 游戏物体的激活与失活 游戏物体的查找 1. 名称查找(Find) 2. 通过标签查找游戏物体&#xff08;FindGameObjectWithT…

v1.2.70-FastJson的AutoType机制研究

v1.2.70-FastJson的AutoType机制研究 最近在对接Alexa亚马逊语音技能&#xff0c;Smart Home Skill Apis时&#xff0c;有一个配置的JSON字符串是这样的&#xff1a; { "capabilityResources": {"friendlyNames": [{"type": "asset",…

json和axion结合

目录 java中使用JSON对象 在pom.xml中导入依赖 使用 public static String toJSONString(Object object)把自定义对象变成JSON对象 json和axios综合案例 使用的过滤器 前端代码 响应和请求都是普通字符串 和 请求时普通字符串&#xff0c;响应是json字符串 响应的数据是…

使用 Django 连接 MySQL 数据库

文章目录 步骤一&#xff1a;安装必要的库和驱动步骤二&#xff1a;配置数据库连接步骤三&#xff1a;执行数据库迁移步骤四&#xff1a;开始使用 MySQL 数据库创建一个模型迁移模型到数据库使用模型进行数据操作创建新记录&#xff1a;查询记录&#xff1a;更新记录&#xff1…

基于百度接口的实时流式语音识别系统

目录 基于百度接口的实时流式语音识别系统 1. 简介 2. 需求分析 3. 系统架构 4. 模块设计 4.1 音频输入模块 4.2 WebSocket通信模块 4.3 音频处理模块 4.4 结果处理模块 5. 接口设计 5.1 WebSocket接口 5.2 音频输入接口 6. 流程图 程序说明文档 1. 安装依赖 2.…

Element ui图片上传

前言 对于广大小白来说&#xff0c;图片上传简直是上传难&#xff0c;难于上青天&#xff01;废话不多说&#xff0c;步入正题&#xff0c;您就瞧好吧&#xff01; 步骤一&#xff1a;前端使用element ui组件&#xff08;upload上传&#xff09; 我个人喜欢使用第二个组件&a…

运放应用1 - 反相放大电路

1.前置知识 反相放大电路存在 负反馈电路 &#xff0c;工作在线性区&#xff0c;可以利用 虚短 概念来分析电路。 注&#xff1a;运放的 虚断 特性是一直存在的&#xff0c;虚短特性则需要运放工作在 线性区 有关运放的基础知识&#xff0c;可以参考我的另外一篇文章&#xff…