【ETCD】【源码阅读】 深入解析 raftNode.start`函数:Raft 核心启动逻辑剖析

raftNode.start方法 是 etcd 中 Raft 模块的核心启动点,其职责是管理 Raft 状态机的状态变迁、日志处理及集群通信等逻辑。通过对源码的逐行分析,我们将全面揭示其运行机制,探讨其设计背后的分布式系统理念。


函数核心结构

raftNode.start 方法在一个新的 goroutine 中启动了 Raft 主循环,核心逻辑是通过 for-select 结构不断处理以下任务:

  1. 定时器驱动的 Raft 心跳与选举。
  2. 接收并处理 Raft 的状态变更。
  3. 应用已提交的日志。
  4. 管理快照和硬状态的持久化。
  5. 发送消息以维持集群通信。

逐步拆解与分析

1. 初始化与 goroutine 启动

go func() {defer r.onStop()islead := false
  • onStop:确保 goroutine 优雅退出时清理资源。
  • islead:标记当前节点是否为领导者(Leader),影响后续消息发送与日志处理。

2. 定时心跳驱动

case <-r.ticker.C:r.tick()
  • 作用
    • Raft 使用定时器驱动节点的选举与心跳逻辑。
    • 调用 r.tick(),触发内部逻辑,包括增加心跳计数器或超时选举。
  • 意义:这是 Raft 协议中维持活跃性的核心机制。

3. 处理 Ready 状态

case rd := <-r.Ready():

Ready 是 Raft 状态机生成的待处理对象,包含领导者变更、已提交日志、快照等状态信息。

处理领导者变更
if rd.SoftState != nil {newLeader := rd.SoftState.Lead != raft.None && rh.getLead() != rd.SoftState.Leadif newLeader {leaderChanges.Inc()}if rd.SoftState.Lead == raft.None {hasLeader.Set(0)} else {hasLeader.Set(1)}rh.updateLead(rd.SoftState.Lead)islead = rd.RaftState == raft.StateLeaderif islead {isLeader.Set(1)} else {isLeader.Set(0)}rh.updateLeadership(newLeader)r.td.Reset()
}
  • SoftState:包含领导者 ID 及节点状态(LeaderFollower)。
  • updateLead:更新领导者信息。
  • updateLeadership:处理领导者身份的切换,包括暂停或恢复租约管理及日志压缩。
应用已提交日志
ap := toApply{entries:       rd.CommittedEntries,snapshot:      rd.Snapshot,notifyc:       notifyc,raftAdvancedC: raftAdvancedC,
}
updateCommittedIndex(&ap, rh)select {
case r.applyc <- ap:
case <-r.stopped:return
}
  • CommittedEntries:已被集群达成共识的日志。
  • updateCommittedIndex:更新已提交的日志索引。
  • applyc 通道:将日志传递给状态机应用层。
消息发送与持久化
if islead {r.transport.Send(r.processMessages(rd.Messages))
}
if err := r.storage.Save(rd.HardState, rd.Entries); err != nil {r.lg.Fatal("failed to save Raft hard state and entries", zap.Error(err))
}
  • 领导者:并行发送日志复制消息(Messages)给其他节点。
  • 持久化:存储日志条目(Entries)与硬状态(HardState),确保数据可靠性。
快照处理
if !raft.IsEmptySnap(rd.Snapshot) {if err := r.storage.SaveSnap(rd.Snapshot); err != nil {r.lg.Fatal("failed to save Raft snapshot", zap.Error(err))}notifyc <- struct{}{}r.raftStorage.ApplySnapshot(rd.Snapshot)r.lg.Info("applied incoming Raft snapshot", zap.Uint64("snapshot-index", rd.Snapshot.Metadata.Index))
}
  • 保存快照:优先持久化快照,保证系统能够从快照中恢复。
  • 应用快照:将快照数据加载到 Raft 存储,更新系统状态。

4. 通信与配置变更

confChanged := false
for _, ent := range rd.CommittedEntries {if ent.Type == raftpb.EntryConfChange {confChanged = truebreak}
}if confChanged {select {case notifyc <- struct{}{}:case <-r.stopped:return}
}
  • 配置变更:处理 EntryConfChange 类型的日志,涉及集群成员的增加或删除。
  • 同步机制:确保配置变更日志在所有节点应用后生效。

5. 优雅退出

case <-r.stopped:return
  • 关闭信号:通过监听 r.stopped 通道,结束循环并退出 goroutine。

设计亮点与分布式理念

  1. 解耦与扩展性

    • Raft 状态的变更通过 Ready 对象传递。
    • 应用层通过 applyc 通道独立处理日志,增强模块化设计。
  2. 并行与性能优化

    • 领导者通过并行发送日志复制消息提升性能。
    • 快照优先持久化,避免数据不一致。
  3. 可靠性

    • 所有状态变更均通过持久化操作保证数据一致性。
    • 通过定时器和心跳机制维持集群活跃。

总结

raftNode.start 是 etcd 中实现 Raft 协议的核心方法,涵盖了领导者选举、日志复制、状态持久化及快照管理等功能。其设计不仅符合 Raft 协议的理论要求,还通过模块化和并行优化,提升了分布式系统的可靠性与性能。

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

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

相关文章

车站值班员题库

1. 联系用手信号显示十、五、三车距离信号中的“三车”&#xff08;约33m&#xff09;信号时&#xff0c;昼间的显示方式为展开的绿色信号旗单臂平伸下压 &#xff08; 一 &#xff09;次。J442 2. 联系用手信号显示股道号码时&#xff0c;昼间右臂向上直伸&#xff0c…

BI中场战事:国外厂商退,国产厂商进

从沉睡的黄金到经济的新宠&#xff0c;数据要素正上演华丽转身。 近年来&#xff0c;数字经济的长驱向前&#xff0c;离不开数据要素价值释放所带来的持续动力。作为第五大生产要素&#xff0c;数据要素的价值释放需要从数据采集、传输到存储、治理&#xff0c;再到分析和可视…

2024年华中杯数学建模C题基于光纤传感器的平面曲线重建算法建模解题全过程文档及程序

2024年华中杯数学建模 C题 基于光纤传感器的平面曲线重建算法建模 原题再现 光纤传感技术是伴随着光纤及光通信技术发展起来的一种新型传感器技术。它是以光波为传感信号、光纤为传输载体来感知外界环境中的信号&#xff0c;其基本原理是当外界环境参数发生变化时&#xff0c…

【LeetCode每日一题】LeetCode 209.长度最小的子数组

LeetCode 209.长度最小的子数组 题目描述 给定一个正整数数组 nums 和一个正整数 target&#xff0c;找出连续子数组的最小长度&#xff0c;使得子数组的和大于或等于 target。如果不存在符合条件的子数组&#xff0c;返回 0。 Java 实现代码 public class Solution {publi…

【openwrt】openwrt-21.02 基于IP地址使用ipset实现策略路由操作说明

openwrt版本信息 DISTRIB_ID=OpenWrt DISTRIB_RELEASE=21.02-SNAPSHOT DISTRIB_REVISION=r0-6bf6af1d5 DISTRIB_TARGET=mediatek/mt7981 DISTRIB_ARCH=aarch64_cortex-a53 DISTRIB_DESCRIPTION=OpenWrt 21.02-SNAPSHOT r0-6bf6af1d5 DISTRIB_TAINTS=no-all busybox override …

【H2O2|全栈】MySQL的基本操作(三)

目录 前言 开篇语 准备工作 案例准备 多表查询 笛卡尔积 等值连接 外连接 内连接 自连接 子查询 存在和所有 含于 分页查询 建表语句 结束语 前言 开篇语 本篇继续讲解MySQL的一些基础的操作——数据字段的查询中的多表查询和分页查询&#xff0c;与单表查询…

从单体到微服务:如何借助 Spring Cloud 实现架构转型

一、Spring Cloud简介 Spring Cloud 是一套基于 Spring 框架的微服务架构解决方案&#xff0c;它提供了一系列的工具和组件&#xff0c;帮助开发者快速构建分布式系统&#xff0c;尤其是微服务架构。 Spring Cloud 提供了诸如服务发现、配置管理、负载均衡、断路器、消息总线…

yarn : 无法加载文件 C:\Users\L\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁

关于执行安装yarn命令后执行yarn -v报错&#xff1a; 先确认执行安装yarn命令是否有误 # 安装yarn npm install yarn -g 终端输入set-ExecutionPolicy RemoteSigned 当然如果yarn -v仍然执行失败&#xff0c;考虑使用管理员方式运行IDEA&#xff0c; 注&#xff1a;如上操作…

centos 常见问题处理

免密登录配置 # 在当前机器下 执行命令 生成 私钥和公钥 ~/.ssh 目录下 ssh-keygen -t rsa # 执行如下命令 把公钥 放到 对应机器上的 ~/.ssh/authorized_keys ssh-copy-id 172.17.68.220 # 如此 两台机器两两配置 centos ssh连接慢 vim /etc/ssh/sshd_config # UseD…

java全栈day12-后端Web实战(IOC+DI)

前言&#xff1a;前面的基础知识了解后进入实战篇&#xff0c;从以下四个方面进行准备 一、开发规范 1.1前后端分离开发 前言回顾 二、Restful风格 引言&#xff1a;前端与后端在进行交互的时候&#xff0c;所使用的url风格叫Restful。 2.1概述 小结 2.2环境准备 2.2.1apif…

链式设计模式——装饰模式和职责链模式

一、装饰模式 1、概述 动态地给一个对象添加一些额外的职责&#xff0c;就增加功能来说&#xff0c;装饰模式比生成子类更为灵活。 ConcreteComponent &#xff1a;是定义了一个具体的对象&#xff0c;可以给这个对象添加一些职责&#xff1b;Decorator &#xff1a;装饰抽象…

Cmake+基础命令

一、版本要求&#xff1a; 检查 cmake 版本号的最低要求&#xff0c;不满足条件时报错。 cmake_minimum_required(VERSION <version>)参数&#xff1a; version&#xff1a;最低要求的版本号 例子&#xff1a; # 最低要求安装3.21版本的cmake cmake_minimum_required…

Java——容器(单例集合)(上)

一 容器介绍 容器&#xff0c;是用来容纳物体、管理物体。生活中,我们会用到各种各样的容器。如锅碗瓢盆、箱子和包等 程序中的“容器”也有类似的功能&#xff0c;用来容纳和管理数据。比如&#xff0c;如下新闻网站的新闻列表、教育网站的课程列表就是用“容器”来管理 视频…

word poi-tl 表格功能增强,实现表格功能垂直合并

目录 问题解决问题poi-tl介绍 功能实现引入依赖模版代码效果图 附加&#xff08;插件实现&#xff09;MergeColumnData 对象MergeGroupData 类ServerMergeTableData 数据信息ServerMergeTablePolicy 合并插件 问题 由于在开发功能需求中&#xff0c;word文档需要垂直合并表格&…

OpenCV相机标定与3D重建(11)机器人世界手眼标定函数calibrateRobotWorldHandEye()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算机器人世界/手眼标定&#xff1a; w T b _{}^{w}\textrm{T}_b w​Tb​ 和 c T g _{}^{c}\textrm{T}_g c​Tg​。 cv::calibrateRobotWorldHa…

GPT系列模型简要概述

GPT-1&#xff1a;&#xff08;0.117B参数量&#xff0c;0.8B words预训练数据) 动机&#xff1a; 在RNN和Transformer之间&#xff0c;选择了后者。 和《All your need is Attention》翻译模型的Encoder-Decoder架构相比&#xff0c;只保留Decoder&#xff0c;因此去掉了Cross…

汽车升级到底应不应该设置“可取消“功能

最近&#xff0c;汽车OTA&#xff08;Over-the-Air&#xff09;升级频频成为车主讨论的热点。有些车主反映&#xff0c;一些升级增加了实用功能&#xff0c;而另一些却让体验变得复杂甚至带来不便。于是&#xff0c;大家不禁发问&#xff1a;汽车升级功能究竟应不应该允许“可取…

单片机 PCB 设计要点

一、引言 单片机作为现代科技的重要组成部分&#xff0c;其 PCB 设计至关重要。本文将详细介绍单片机 PCB 设计的要点和流程&#xff0c;帮助读者更好地掌握这一关键技术。 在电子世界的浩瀚星海中&#xff0c;单片机无疑是现代科技中一颗闪烁的明珠。作为掌握嵌入式系统的基…

Django+Apscheduler 开发定时任务模块【六】

目录 回顾 前五个文章讲述了django-autojob的部分代码和执行逻辑 【DjangoApscheduler 开发定时任务模块】【一】 【DjangoApscheduler 开发定时任务模块】【二】 【DjangoApscheduler 开发定时任务模块】【三】 【DjangoApscheduler 开发定时任务模块】【四】 【DjangoApsch…

Ubuntu中配置交叉编译工具的三条命令的详细研究

关于该把下面的三条交叉编译配置语句加到哪里&#xff0c;详情见 https://blog.csdn.net/wenhao_ir/article/details/144326545 的第2点。 现在试解释下面三条交叉编译配置语句&#xff1a; export ARCHarm export CROSS_COMPILEarm-buildroot-linux-gnueabihf- export PATH$…