当前位置: 首页 > news >正文

Nacos 是如何实现 Raft 协议的?Raft 协议的关键组件和流程是什么?

在这里插入图片描述

Nacos 如何实现 Raft 协议?

Nacos 自身并没有从零开始实现 Raft 协议。它采用了更成熟的做法:

  1. 集成成熟的 Raft 库: Nacos (特别是 Nacos 2.x 版本) 集成了一个成熟、经过生产验证的 Raft 协议实现库。最核心的是 JRaft(一个基于 Java 的 Raft 算法实现,源自蚂蚁集团/Alipay)。通过集成 JRaft,Nacos 直接利用其提供的 Raft 能力,处理复杂的 Raft 细节,如日志复制、领导者选举、成员变更等。

  2. 应用范围: Nacos 主要在 集群模式 下使用 Raft 协议,并为 CP (Consistency Protocol) 提供了良好的支持。Raft 在 Nacos 中主要用于:

    • Nacos 服务器节点间的领导者选举 (Leader Election): 在 Nacos 集群中,需要有一个 Leader 节点来负责处理写操作或协调任务,以保证数据的一致性。Raft 协议被用来在集群节点中自动选举出Leader。
    • 元数据和关键数据的一致性: 对于需要强一致性的数据(例如服务的元数据、持久化的配置信息、集群节点信息等),Nacos 会利用 Raft 的日志复制机制,确保这些数据在集群中的多数派节点上达成一致。当 Leader 收到写请求时,它会将操作记录为一条日志条目,通过 Raft 协议将这条日志复制给 Follower 节点,只有当日志被多数派节点确认后,操作才会被提交并应用到状态机(即 Nacos 的业务数据存储)。
    • 集群成员管理: Raft 也参与管理 Nacos 集群自身的成员变更(节点的加入和离开)。
  3. 与 Nacos 业务逻辑的结合:

    • Nacos 将需要通过 Raft 保证一致性的操作封装成 Raft 的日志条目 (Log Entry)
    • Nacos 将其业务数据存储(如内存中的服务注册表、配置信息等)作为 Raft 的状态机 (State Machine)
    • 当 Raft 协议确定一条日志条目已经被提交 (Committed) 后,Nacos 会调用 JRaft 提供的回调接口,将这条日志条目中的操作应用 (Apply) 到自己的状态机上,从而更新业务数据。

重要区分:

  • 并非所有数据都走 Raft: Nacos 为了性能和可用性,区分了 AP (Availability Priority) 和 CP (Consistency Priority) 数据。对于服务实例的注册与发现这类要求高可用和高性能的数据(AP 数据),Nacos 2.x 主要使用其自研的 Distro 协议(一种类 Gossip 的协议,优化了AP场景下的数据同步)进行节点间的数据同步,而不是 Raft。只有那些明确标记为需要强一致性(CP)的数据或操作(如持久化服务、部分配置管理操作、集群管理)才会走 Raft 协议。

Raft 协议的关键组件和流程

Raft 是一种比 Paxos 更易于理解和实现的分布式一致性算法。它的核心思想是将一致性问题分解为三个相对独立的子问题:

  1. 领导者选举 (Leader Election):

    • 组件:
      • 节点角色:
        • Leader (领导者): 集群中同一时间只能有一个 Leader。它负责处理所有客户端的请求(写操作),管理日志复制,并向 Follower 发送心跳。
        • Follower (跟随者): 被动角色。响应来自 Leader 和 Candidate 的请求。如果一段时间内没有收到 Leader 的心跳,就会转变为 Candidate并发起选举。
        • Candidate (候选人): 用于选举新 Leader 的临时角色。Follower 超时后转变为 Candidate,向其他节点请求投票。
      • 任期 (Term): 如果 Candidate 赢得选举,它在该任期内担任 Leader。如果选举失败(没有获得多数票),则退回 Follower 状态,任期用于检测过期的信息。
    • 流程:
      • 初始状态或 Leader 失联后,Follower 在等待 Leader 心跳超时后,增加自己的当前任期号,转变为 Candidate。
      • Candidate 向集群中的其他所有节点发送 RequestVote RPC(远程过程调用),请求投票。
      • 其他节点收到 RequestVote 请求后,如果在当前任期内尚未投票给其他 Candidate,并且 Candidate 的日志至少和自己一样 (Raft 的安全性保证),则投票给该 Candidate,并重置自己的选举计时器。
      • Candidate 如果收到了来自集群多数派节点的投票,则赢得选举,成为新的 Leader。
      • 成为 Leader 后,立即向所有 Follower 发送心跳(空的 AppendEntries RPC)以宣告自己的领导地位,并阻止新的选举发生。
      • 如果在选举期间,Candidate 收到了来自具有更高或相等任期的新 Leader 的 AppendEntries RPC,则承认该 Leader,并立即转变为 Follower。
      • 如果选举超时(例如发生网络分区导致选票分裂),没有 Candidate 获得多数票,则当前任期结束,Candidate 增加任期号,开始新一轮选举(通过随机化的选举减少冲突)。
  2. 日志复制 (Log Replication):

    • 组件:
      • 复制日志 (Replicated Log): 每个节点都维护一个包含一系列命令(操作)的日志。日志条目按顺序编号(索引),并包含对应的任期号。
      • 状态机 (State Machine): 实际存储业务数据的地方。所有节点的状态机初始状态相同。
      • 提交索引 (Commit Index): Leader 维护的所有日志条目的索引。
    • 流程:
      • 客户端的写请求首先发送给 Leader。
      • Leader 将该操作作为一个新的日志条目追加到自己的日志末尾。
      • Leader 通过 AppendEntries RPC 并行的将新的日志条目发送给所有 Follower。
      • Follower 收到 AppendEntries 请求后,进行一致性检查(检查前一个日志条目的索引和任期是否匹配),如果通过,则将新的日志条目追加到自己的日志中,并向 Leader 发送成功响应。
      • 当 Leader 收到多数派 Follower 对某个日志条目的成功响应后,Leader 就认为该日志条目是已提交 (Committed) 的。Leader 会更新自己的 Commit Index
      • Leader 在后续的 AppendEntries RPC(包括心跳)中,会告知 Follower 当前的 Commit Index
      • Follower 收到 Leader 的 Commit Index 后,会知道哪些日志条目是已提交的。
      • 节点(包括 Leader 和 Follower)按顺序将已提交的日志条目应用(Apply)到自己的状态机中,更新业务数据。Raft 保证所有节点最终会以相同的顺序应用相同的日志条目。
  3. 安全性 (Safety):

    • Raft 包含多项机制来确保系统的一致性和正确性(即使在发生网络分区、节点崩溃等故障):
      • 选举安全 (Election Safety): 每个任期内只有一个 Leader 会被选举出来。
      • 领导者只追加 (Leader Append-Only): Leader 不会覆盖或删除自己的日志条目,只会追加。
      • 日志匹配 (Log Matching Property): 如果两个不同日志中的条目拥有相同的索引和任期号,那么它们存储的命令是相同的,并且它们之前的所有日志条目也都完全相同。这是通过 AppendEntries 中的一致性检查实现的。
      • 领导者完整性 (Leader Completeness Property): 如果某个日志条目在某个任期被提交了,那么它一定会出现在所有更高任期的 Leader 的日志中。
      • 状态机安全 (State Machine Safety Property): 如果一个节点已经将某个索引的日志条目应用到其状态机,那么其他任何节点在相同索引位置应用的一定是相同的日志条目。这是因为只有已提交的日志才能被应用。

总结: Nacos 利用 JRaft 库实现了 Raft 协议,主要用于 Nacos 集群自身的 Leader 选举和 CP 数据的强一致性同步。Raft 协议通过领导者选举、日志复制和一系列安全性机制,确保了分布式环境下数据的一致性。

http://www.xdnf.cn/news/91045.html

相关文章:

  • Java基础复习(JavaSE进阶)第八章 多线程
  • C++静态与动态联编区别解析
  • Vue3简介
  • TDengine 查询引擎设计
  • 滑动模式观测器(Sliding mode observer)
  • 机器视觉的液晶屏点胶应用
  • 飞搭系列 | 组件增加标记,提升用户体验
  • android开发-BuildConfig无法生成
  • [Java · 铢积寸累] 数据结构 — 二维数组 - 概念引入
  • 潮玩+智显 |电子价签演绎潮玩信息智显的百变状态
  • Linux系统之----进程的概念
  • GpuGeek:以弹性算力与全栈服务赋能产业智能升级
  • 继承相关知识
  • Kinibi-610a:面向芯片厂商与设备制造商的TEE升级详解
  • 学习笔记:黑马程序员JavaWeb开发教程(2025.3.25)
  • ctfshow web类 2-7题
  • pip的源管理和包管理
  • 初级云计算运维工程师学习二
  • DAS(分布式声波传感)工作流程
  • Windows:删除文件报(已解决)操作无法完成,因为其中的文件夹或文件已在另一程序中打开
  • 关于QLabel上显示图片扩展的问题记录
  • 文件操作函数
  • PLOG安装
  • NumPy入门:从数组基础到数学运算
  • 深度学习中的“重参数化”总结
  • 正点原子TFTLCD扩展
  • 框架开发.idea配置项提示
  • 【算法】BFS-解决FloodFill问题
  • 基于 Spring Boot实现的图书管理系统
  • 强化学习框架:OpenRLHF源码解读,模型处理