Raft如何做到线性一致性
一、为什么需要请求去重考虑一次Append(name, A)1. 客户端发送 Append 请求 2. Leader 将请求提交到 Raft 日志 3. KV 状态机执行成功name 变成 A 4. 服务端返回响应 5. 但响应在网络中丢失 6. 客户端超时重新发送同一个请求如果服务端无法识别重试Append会再次执行第一次执行name A 第二次执行name AA客户端实际上只请求了一次状态机却执行了两次这会破坏客户端期望的语义。因此必须给每个逻辑请求一个唯一身份。二、ClientId和CommandId分别是什么图中每个客户端维护两个重要信息。ClientId表示客户端身份例如客户端AClientId C1001 客户端BClientId C2001项目中Clerk创建时会生成客户端 ID并将请求序号初始化为 0Clerk::Clerk() : m_clientId(Uuid()), m_requestId(0), m_recentLeaderId(0) {}CommandId在项目中叫RequestId表示该客户端发出的第几个逻辑请求(C1001, 1) - Put(x, A) (C1001, 2) - Append(x, B) (C1001, 3) - Get(x)每次产生一个新的逻辑请求时客户端将m_requestId加一m_requestId; auto requestId m_requestId;三、为什么必须是二元组唯一请求标识是(ClientId, RequestId)不能只使用ClientId因为一个客户端会发送很多请求。不能只使用RequestId因为不同客户端都可能存在RequestId 1(C1001, 1) (C2001, 1)这显然是两个不同请求。因此ClientId RequestId共同构成一个类似“幂等键”的东西。项目中的 Raft 命令Op包含这两个字段class Op { public: std::string Operation; std::string Key; std::string Value; std::string ClientId; int RequestId; };四、重试时 RequestId 不能增加这是图中非常关键的一点。新的逻辑请求才增加RequestId第一次业务操作RequestId 10 第二次业务操作RequestId 11同一个请求因为超时而重试时必须继续使用原来的 ID发送请求(C1001, 11) 超时重试(C1001, 11) 再次重试(C1001, 11)不能变成 12、13否则服务端会认为它们是三个不同请求。这个项目做得是对的requestId在进入重试循环之前保存循环中始终复用它m_requestId; auto requestId m_requestId; while (true) { args.set_requestid(requestId); // 向不同服务器重试 }五、服务端如何判断重复请求每个 KV Server 保存std::unordered_mapstd::string, int m_lastRequestId;含义是ClientId - 该客户端已经执行过的最大 RequestId例如C1001 - 15 C2001 - 8表示C1001的 1 到 15 号请求已经处理过。判断重复请求的逻辑是return RequestId m_lastRequestId[ClientId];假设m_lastRequestId[C1001] 15那么请求 16新请求可以执行 请求 15重复请求不能再次执行 请求 14旧请求也不能再次执行这就是图中“只执行递增的 CommandId”的具体含义。六、完整的丢包重试过程客户端 C7 发送 (C7, 12, Append(x, A)) Leader 写入 Raft 日志 ↓ 多数节点复制成功 ↓ 日志被提交 ↓ KV 状态机执行 Append ↓ lastRequestId[C7] 12 ↓ 响应丢失 ↓ 客户端重试同一个 (C7, 12) ↓ 服务端发现 12 lastRequestId[C7] ↓ 不再执行 Append直接返回成功项目在 Raft 提交命令后调用ifRequestDuplicate()只有非重复请求才操作 KV 数据if (!ifRequestDuplicate(op.ClientId, op.RequestId)) { if (op.Operation Put) { ExecutePutOpOnKVDB(op); } if (op.Operation Append) { ExecuteAppendOpOnKVDB(op); } }执行 KV 操作时还会更新m_lastRequestId[op.ClientId] op.RequestId;KV 状态和去重信息在同一把互斥锁保护下更新这一点很重要。七、它与线性一致性的关系线性一致性要求每个操作看起来都在某一个瞬间原子完成而且不能违反真实时间顺序。Raft主要解决所有节点按照相同的日志顺序执行命令请求去重解决客户端的一次逻辑操作即使多次重试也只产生一次状态变化二者缺一不可。例如没有去重时Raft可能完全正确地提交两条相同的Append日志。Raft不知道它们是同一次请求的重试因为对 Raft 来说它们只是两条合法命令。所以更准确地说Raft提供一致的提交顺序ClientId RequestId提供重试情况下的至多一次执行语义二者共同支撑线性一致的客户端体验。网络层无法真正保证消息“只发送一次”这里只能保证重复消息不会导致状态机重复生效。

相关新闻

JWT解析工具

JWT解析工具

JWT令牌怎么解码查看?在线JWT解析工具教程 前后端分离项目中,JWT(JSON Web Token)是最常用的身份认证方式。但拿到一串 xxxxx.yyyyy.zzzzz 的 token,根本看不出里面存了什么信息、什么时候过期。本文教你用盘子工具站…

2026/10/20 2:01:30 阅读更多 →
OpenHarmony系统Python3.13.5移植实战指南

OpenHarmony系统Python3.13.5移植实战指南

1. 项目背景与挑战去年在为一个工业物联网项目选型时,客户要求必须在OpenHarmony系统上运行Python数据分析脚本。当时市面上还没有成熟的Python3移植方案,这直接促使我开始了将Python3.13.5移植到OpenHarmony的工作。OpenHarmony作为新一代分布式操作系统…

2026/10/17 3:00:44 阅读更多 →
不要问模型是 Transformer 还是 Diffusion:一套五层技术栈检查法(系统角色 / 表示空间 / 网络骨架 / 训练范式 / 推理算法)

不要问模型是 Transformer 还是 Diffusion:一套五层技术栈检查法(系统角色 / 表示空间 / 网络骨架 / 训练范式 / 推理算法)

不要问模型是 Transformer 还是 Diffusion:一套五层技术栈检查法 摘要 Transformer、VAE、Diffusion、Flow 和 Solver 经常被放在同一张比较表里,但它们回答的是不同问题。本文建立系统角色、表示空间、网络骨架、训练/生成范式和推理算法五层检查法&…

2026/10/18 5:17:25 阅读更多 →

最新新闻

EfficientNetV2架构深度解析:tf_efficientnetv2_b3.in1k为何能又快又小?

EfficientNetV2架构深度解析:tf_efficientnetv2_b3.in1k为何能又快又小?

【免费下载链接】tf_efficientnetv2_b3.in1k 项目地址: https://ai.gitcode.com/hf_mirrors/timm/tf_efficientnetv2_b3.in1k 点击查看 免费下载 本文以开源预训练模型 tf_efficientnetv2_b3.in1k 为例,带你快速看懂这个图像分类模型:它仅用…

2026/10/20 2:01:14 阅读更多 →
GhostTrack:IP归属、号码归属与用户名注册速查——不用开浏览器

GhostTrack:IP归属、号码归属与用户名注册速查——不用开浏览器

GhostTrack:IP归属、号码归属与用户名注册速查——不用开浏览器 【免费下载链接】GhostTrack Useful tool to track location or mobile number 项目地址: https://gitcode.com/GitHub_Trending/gh/GhostTrack GhostTrack 是一个 Python 编写的 OSINT 脚本&a…

2026/10/20 2:01:14 阅读更多 →
Linux内核6.x学习路线:从环境搭建到调试进阶的专栏指南

Linux内核6.x学习路线:从环境搭建到调试进阶的专栏指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 2:01:14 阅读更多 →
树莓派与Arduino选型指南:打破裸机/系统二分法

树莓派与Arduino选型指南:打破裸机/系统二分法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 2:01:14 阅读更多 →
Linux显示驱动调试工具链:从DRM/KMS到PHY寄存器的全栈诊断

Linux显示驱动调试工具链:从DRM/KMS到PHY寄存器的全栈诊断

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 2:01:14 阅读更多 →
Unity代码热更新实战:ILRuntime集成Addressable的完整方案与避坑指南

Unity代码热更新实战:ILRuntime集成Addressable的完整方案与避坑指南

做Unity客户端这些年,只要是做手游的,基本绕不开热更新这个话题。资源热更还好说,AssetBundle或者Addressable都能解决,真正麻烦的是代码热更。以前用Lua,好是好,但团队要养Lua程序员,C#的代码也…

2026/10/20 2:00:13 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →