一、快速了解Raft算法

Raft 适用于一个管理日志一致性的协议,相比于 Paxos 协议 Raft 更易于理解和去实现它。

为了提高理解性,Raft 将一致性算法分为了几个部分,包括领导选取(leader selection)、日志复制(log replication)、安全(safety),并且使用了更强的一致性来减少了必须需要考虑的状态。

相比Paxos,Raft算法理解起来更加直观。

Raft算法将Server划分为3种状态,或者也可以称作角色:

  • Leader

    负责Client交互和log复制,同一时刻系统中最多存在1个。

  • Follower

    被动响应请求RPC,从不主动发起请求RPC。

  • Candidate

一种临时的角色,只存在于leader的选举阶段,某个节点想要变成leader,那么就发起投票请求,同时自己变成candidate。如果选举成功,则变为candidate,否则退回为follower

状态或者说角色的流转如下:

在Raft中,问题分解为:领导选取、日志复制、安全和成员变化。

复制状态机通过复制日志来实现:

日志:每台机器保存一份日志,日志来自于客户端的请求,包含一系列的命令

状态机:状态机会按顺序执行这些命令

一致性模型:分布式环境下,保证多机的日志是一致的,这样回放到状态机中的状态是一致的

Raft算法选主流程

Raft中有Term的概念,Term类比中国历史上的朝代更替,Raft 算法将时间划分成为任意不同长度的任期(term)。

选举流程

1、follower增加当前的term,转变为candidate。

2、candidate投票给自己,并发送RequestVote RPC给集群中的其他服务器。

3、收到RequestVote的服务器,在同一term中只会按照先到先得投票给至多一个candidate。且只会投票给log至少和自身一样新的candidate。

关于Raft更详细的描述,可以查看这里,从分布式一致性到共识机制(二)Raft算法

二、Nacos中的CP一致性

Spring Cloud Alibaba Nacos 在 1.0.0 正式支持 AP 和 CP 两种一致性协议,其中的CP一致性协议实现,是基于简化的 Raft 的 CP 一致性。

如何实现Raft算法

Nacos server在启动时,会通过RunningConfig.onApplicationEvent()方法调用RaftCore.init()方法。

启动选举

public static void init() throws Exception {

    Loggers.RAFT.info("initializing Raft sub-system");

    // 启动Notifier,轮询Datums,通知RaftListener
executor.submit(notifier); // 获取Raft集群节点,更新到PeerSet中
peers.add(NamingProxy.getServers()); long start = System.currentTimeMillis(); // 从磁盘加载Datum和term数据进行数据恢复
RaftStore.load(); Loggers.RAFT.info("cache loaded, peer count: {}, datum count: {}, current term: {}",
peers.size(), datums.size(), peers.getTerm()); while (true) {
if (notifier.tasks.size() <= 0) {
break;
}
Thread.sleep(1000L);
System.out.println(notifier.tasks.size());
} Loggers.RAFT.info("finish to load data from disk, cost: {} ms.", (System.currentTimeMillis() - start)); GlobalExecutor.register(new MasterElection()); // Leader选举
GlobalExecutor.register1(new HeartBeat()); // Raft心跳
GlobalExecutor.register(new AddressServerUpdater(), GlobalExecutor.ADDRESS_SERVER_UPDATE_INTERVAL_MS); if (peers.size() > 0) {
if (lock.tryLock(INIT_LOCK_TIME_SECONDS, TimeUnit.SECONDS)) {
initialized = true;
lock.unlock();
}
} else {
throw new Exception("peers is empty.");
} Loggers.RAFT.info("timer started: leader timeout ms: {}, heart-beat timeout ms: {}",
GlobalExecutor.LEADER_TIMEOUT_MS, GlobalExecutor.HEARTBEAT_INTERVAL_MS);
}

在init方法主要做了如下几件事:

  1. 获取Raft集群节点 peers.add(NamingProxy.getServers());
  2. Raft集群数据恢复 RaftStore.load();
  3. Raft选举 GlobalExecutor.register(new MasterElection());
  4. Raft心跳 GlobalExecutor.register(new HeartBeat());
  5. Raft发布内容
  6. Raft保证内容一致性

选举流程

其中,raft集群内部节点间是通过暴露的Restful接口,代码在 RaftController 中。

RaftController控制器是raft集群内部节点间通信使用的,具体的信息如下

POST HTTP://{ip:port}/v1/ns/raft/vote : 进行投票请求

POST HTTP://{ip:port}/v1/ns/raft/beat : Leader向Follower发送心跳信息

GET HTTP://{ip:port}/v1/ns/raft/peer : 获取该节点的RaftPeer信息

PUT HTTP://{ip:port}/v1/ns/raft/datum/reload : 重新加载某日志信息

POST HTTP://{ip:port}/v1/ns/raft/datum : Leader接收传来的数据并存入

DELETE HTTP://{ip:port}/v1/ns/raft/datum : Leader接收传来的数据删除操作

GET HTTP://{ip:port}/v1/ns/raft/datum : 获取该节点存储的数据信息

GET HTTP://{ip:port}/v1/ns/raft/state : 获取该节点的状态信息{UP or DOWN}

POST HTTP://{ip:port}/v1/ns/raft/datum/commit : Follower节点接收Leader传来得到数据存入操作

DELETE HTTP://{ip:port}/v1/ns/raft/datum : Follower节点接收Leader传来的数据删除操作

GET HTTP://{ip:port}/v1/ns/raft/leader : 获取当前集群的Leader节点信息

GET HTTP://{ip:port}/v1/ns/raft/listeners : 获取当前Raft集群的所有事件监听者
RaftPeerSet

心跳机制

Raft中使用心跳机制来触发leader选举。心跳定时任务是在GlobalExecutor 中,

通过 GlobalExecutor.register(new HeartBeat())注册心跳定时任务,具体操作包括:

  • 重置Leader节点的heart timeout、election timeout;
  • sendBeat()发送心跳包
 public class HeartBeat implements Runnable {
@Override
public void run() {
try { if (!peers.isReady()) {
return;
} RaftPeer local = peers.local();
local.heartbeatDueMs -= GlobalExecutor.TICK_PERIOD_MS;
if (local.heartbeatDueMs > 0) {
return;
} local.resetHeartbeatDue(); sendBeat();
} catch (Exception e) {
Loggers.RAFT.warn("[RAFT] error while sending beat {}", e);
} }
}

简单说明了下Nacos中的Raft一致性实现,更详细的流程,可以下载源码,查看 RaftCore 进行了解。源码可以通过以下地址检出:

git clone https://github.com/alibaba/nacos.git

扫码关注公众号:架构进化论,获得第一手的技术资讯和原创文章

对标Eureka的AP一致性,Nacos如何实现Raft算法的更多相关文章

  1. 分布式一致性协议之:Raft算法

    一致性算法Raft详解 背景 熟悉或了解分布性系统的开发者都知道一致性算法的重要性,Paxos一致性算法从90年提出到现在已经有二十几年了,而Paxos流程太过于繁杂实现起来也比较复杂,可能也是以为过 ...

  2. eureka的简单介绍,eureka单节点版的实现?eureka的自我保护?eureka的AP性,和CP性?

    注意!!! 这是对上一篇博客 springcloud的延续,整个项目的搭建,来源与上一篇博客.一.什么是eureka? // eureka是一个注册中心,实现了dubbo中zookeeper的效果! ...

  3. 搞懂分布式技术2:分布式一致性协议与Paxos,Raft算法

    搞懂分布式技术2:分布式一致性协议与Paxos,Raft算法 2PC 由于BASE理论需要在一致性和可用性方面做出权衡,因此涌现了很多关于一致性的算法和协议.其中比较著名的有二阶提交协议(2 Phas ...

  4. 分布式一致性算法:Raft 算法(论文翻译)

    Raft 算法是可以用来替代 Paxos 算法的分布式一致性算法,而且 raft 算法比 Paxos 算法更易懂且更容易实现.本文对 raft 论文进行翻译,希望能有助于读者更方便地理解 raft 的 ...

  5. 从分布式一致性到共识机制(二)Raft算法

    春秋五霸说开 春秋五霸,是指东周春秋时期相继称霸主的五个诸侯,“霸”,意为霸主,即是诸侯之领袖.典型的比如齐桓公,晋文公,春秋时期诸侯国的称霸,与今天要讨论的Raft算法很像. 一.更加直观的Raft ...

  6. 【转】分布式一致性算法:Raft 算法(Raft 论文翻译)

    编者按:这篇文章来自简书的一个位博主Jeffbond,读了好几遍,翻译的质量比较高,原文链接:分布式一致性算法:Raft 算法(Raft 论文翻译),版权一切归原译者. 同时,第6部分的集群成员变更读 ...

  7. 理解分布式一致性与Raft算法

    理解分布式一致性与Raft算法 永远绕不开的CAP定理 出于可用性及负载方面考虑,一个分布式系统中数据必然不会只存在于一台机器,一致性简单地说就是分布式系统中的各个部分保持数据一致 但让数据保持一致往 ...

  8. 分布式系统一致性问题与Raft算法(上)

    最近在做MIT6.824的几个实验,真心觉得每一个做分布式相关开发的程序员都应该去刷一遍(裂墙推荐),肯定能够提高自己的技术认知水平,同时也非常感谢MIT能够把这么好的资源分享出来. 其中第二个实验, ...

  9. 分布式系统一致性问题与Raft算法(下)

    上一篇讲述了什么是分布式一致性问题,以及它难在哪里,liveness和satefy问题,和FLP impossibility定理.有兴趣的童鞋可以看看分布式系统一致性问题与Raft算法(上). 这一节 ...

随机推荐

  1. JAXB常用注解讲解(超详细)

    简介: JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术.该过程中,JAXB也提供了将XML实例 ...

  2. 2019-9-20-SharpDx-的代替项目

    title author date CreateTime categories SharpDx 的代替项目 lindexi 2019-09-20 09:13:59 +0800 2019-09-20 0 ...

  3. H3C备份/恢复下次启动配置文件

  4. windows系统锁屏及修改密码项目开发经验记录

    改造windows开机.锁屏登录流程需要使用微软停供的Credential Providers工程,编译出来是dll,安装在C:\windows\system32目录下,然后注册注册表(运行工程生成的 ...

  5. MySQL 命令行(转)

    1.登录mysql 本地:mysql -u root -p, 回车后输入密码; 也可以p后不加空格,直接加密码.回车就登录了 远程:mysql -hxx.xx.xx.xx -u -pxxx 2.查看数 ...

  6. ssh 简写

    << remotessh remotessh 这一对之间,可以写多个命令,换行即可. 否者就简单的 双引号,里面每个命令用分号隔开. 注意: 在远程服务器上的执行权限. 注意:login密 ...

  7. vue学习笔记(三)class和style绑定

    前言 通过上一章的学习vue学习笔记(二)vue的生命周期和钩子函数,我们已经更近一步的知道了关于vue的一些知识,本篇博客将进一步探讨vue其它方面的内容,vue中关于class和style绑定,关 ...

  8. 在springboot环境下tk-mybatis的使用记录

    1. 新建springboot工程 访问https://start.spring.io/,新建一个springboot工程. 自动生成的工程主要的注意点如下: 1)pom.xml <parent ...

  9. kotlin + springboot启用elasticsearch搜索

    参考自: http://how2j.cn/k/search-engine/search-engine-springboot/1791.html?p=78908 工具版本: elasticsearch ...

  10. echarts实现group关系图案例

    官网案例:https://www.echartsjs.com/examples/zh/editor.html?c=graph-simple 自己在项目中实现了两个group图: 1.先看实现效果,两个 ...