Raft如何做到线性一致性
📅 2026/7/31 9:44:40
👁️ 次浏览
一、为什么需要请求去重考虑一次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提供重试情况下的至多一次执行语义二者共同支撑线性一致的客户端体验。网络层无法真正保证消息“只发送一次”这里只能保证重复消息不会导致状态机重复生效。
线性一致性(Linearizability)**是分布式系统中的一种强一致性模型。一句话定义:所有操作看起来都像是在某个唯一时间点瞬间完成,并且这个时间点必须位于操作发起和响应之间,同时不能违背现实时间顺序。核心要求假设有多…
📅 2026/7/31 9:44:40
一句话定位赏金不是奖励,是赎金——厂商买的不是漏洞,是漏洞持有人本来可以造成的灾害。先讲清楚一个前提:黑客的能力,永远以破坏能力为尺度。无论破坏是否已经发生。发现一个能瘫痪全国电网的漏洞,和实际上有没有去瘫…
📅 2026/7/31 9:44:40
摘要小超市用什么收银系统,不能只看扫码收款速度,还要判断商品建档、采购入库、库存扣减、会员促销、员工交接班和经营报表能否形成完整业务闭环。本文从收银系统与普通收款工具的区别入手,分析小超市常见管理痛点,并对智慧记AI零…
📅 2026/7/31 9:44:40
1. 问题场景典型铺货型电商卖家的日常需求:月上新 200-500 SKU,每 SKU 需 8-15 张套图(主图辅图场景图详情图变体图)。总需求 20015 3000 张图/月。传统 AI 出图流程(以 Midjourney V7 为例):…
📅 2026/7/31 10:41:09
1. 项目概述:频率排序字符串数组的核心逻辑字符串数组的频率排序是一个看似简单却蕴含多种Java核心知识点的典型问题。我处理过不少类似需求,比如电商平台的热搜词统计、日志分析中的高频错误提取等场景。本质上,我们需要完成三个关键操作&am…
📅 2026/7/31 10:40:08
终极指南:如何用Chrome文本批量替换插件3分钟完成网页内容高效编辑 【免费下载链接】chrome-extensions-searchReplace 项目地址: https://gitcode.com/gh_mirrors/ch/chrome-extensions-searchReplace
你是否曾为网页上需要批量修改的文本内容而感到头疼&a…
📅 2026/7/31 10:40:08
1. 项目概述:一次关于Flask Session的深度安全探索 最近在复盘一些经典的CTF(Capture The Flag)题目时,又遇到了PicoCTF里的“Most Cookie”这道题。这道题本身难度不算顶尖,但它像一把精巧的钥匙,精准地打…
📅 2026/7/31 10:40:08
1. Shell函数基础概念 在Shell脚本编程中,函数是将一组命令封装起来以便重复使用的代码块。它就像是一个小型脚本中的脚本,能够接收参数、执行特定任务并返回结果。函数在Shell中的定义方式有两种基本语法: 第一种是传统Bourne shell风格&am…
📅 2026/7/31 10:40:08
一、大型活动会务管理的挑战本质
从项目管理视角来看,一场千人规模的会议或高端晚宴,本质上是一个「多节点、高并发、强时效」的复杂项目。以一场典型的企业千人会议为例,项目管理的复杂度表现在以下几个维度:
时间维度࿱…
📅 2026/7/31 10:40:08
数据库复制是把主库数据同步到备库的机制,分为逻辑复制和物理复制两种。逻辑复制传输的是 SQL 语句或行变更事件,物理复制传输的是存储引擎底层的物理日志。阿里云 PolarDB(云原生数据库)采用物理复制,在同步延迟、数据…
📅 2026/7/31 0:00:23
BilibiliDown:3分钟学会B站视频下载的终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bilib…
📅 2026/7/31 0:00:23
当前,游戏行业的“DataAI融合”已从概念验证进入价值落地阶段。根据IDC 2025年数据,中国AI游戏云市场规模已达18.6亿元;同时,游戏研发环节AI渗透率高达86%,生成式AI内容普及率超过50%。面对庞大的市场,游戏…
📅 2026/7/31 0:00:23
更多请点击:
https://codechina.net
第一章:AI帮助理解数学概念 人工智能正以前所未有的方式重塑数学学习的路径。通过自然语言处理与符号计算的深度融合,AI不仅能解析抽象定义,还能将定理、证明和几何直觉转化为可交互、可验证的…
📅 2026/7/31 1:18:08
1. 项目背景与核心价值去年参与的一个短剧项目让我深刻体会到传统创作流程的痛点:编剧团队花了三周打磨剧本,角色设计反复修改了七版,最后成片时又因为演员档期问题不得不临时调整分镜。这种低效的创作模式在快节奏的内容行业越来越难以为继。…
📅 2026/7/31 1:18:08
remix-i18next TypeScript类型安全实践:确保翻译键与类型定义同步 【免费下载链接】remix-i18next The easiest way to translate your React Router framework mode apps 项目地址: https://gitcode.com/gh_mirrors/re/remix-i18next
在开发多语言应用时&am…
📅 2026/7/31 1:18:08
目录
第一步:选对模板,省心一半
第二步:打开扫码点餐功能
开启功能按钮
桌台管理与桌码生成
第三步:个性化设计,打造品牌感
调整点餐页面
设置点餐规则 你还在让顾客站着排队点餐吗?2025年ÿ…
📅 2026/7/31 7:18:38
在业务中快速构建一个能理解私有文档、准确回答专业问题的智能助手,是很多开发团队面临的共同挑战。传统方案往往需要从零开始搭建复杂的 RAG(检索增强生成)系统,涉及文档解析、向量化、检索、大模型调用等多个环节,整…
📅 2026/7/30 17:17:14
FAE放射组学分析工具:医学影像特征探索的完整解决方案 【免费下载链接】FAE FeAture Explorer 项目地址: https://gitcode.com/gh_mirrors/fae/FAE
你是否曾经面对海量医学影像数据感到无从下手?想要从CT、MRI等影像中提取有价值的定量特征&#…
📅 2026/7/31 5:18:28