翔云

Just try, don't shy. 最新文章请点击
随笔 - 294, 文章 - 0, 评论 - 27, 阅读 - 49万
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

raft协议中的日志安全性

Posted on   翔云123456  阅读(152)  评论(0编辑  收藏  举报

1.日志安全性问题

日志安全性是指,
新选出的leader必须包含所有已提交的日志项,已经提交的日志不能因为leader变化被覆盖。

在raft日志复制过程中,follower为了保持与leader一致性,follower的日志可能会被覆盖。

raft是如何保证日志安全性的?

raft有以下几点规则:

  • leader只能日志追加日志,不能覆盖日志。
  • 只有leader的日志项才能被提交,follower不能接收写请求和提交日志。
  • 只有已经提交的日志项,才能被应用到状态机中。
  • 选举时限制新leader日志包含所有已提交日志项。

2.选举限制

选举时,新leader必须包含所有已提交commited的日志项。

commited是指当leader 复制日志时,如果可以复制到多数节点,那么这个日志被任务是提交的(commited)。

例如,如果集群有3个节点,就是至少已经复制到2个节点。

raft中判断两个节点,哪个节点拥有最新日志的方式是比较日志项的term和index:

如果term不同,选择term最大的。

如果term相同,选择index最大的。

3.当前term的日志提交

Leader 通过复制日志项到过半数节点来确认当前任期内的日志项提交成功。

新的leader必须包含已经提交的日志。

如图所示,5个节点的集群中,S1是term 2的leader。
在这里插入图片描述

日志项1、2已复制到所有节点,是commited。

日志项3已复制到4个节点,是commited。

日志项4已复制到3个节点,是commited。

如果在将日志项4复制到S3之后,leader宕机,此时进入leader选举。

那么,由于S4, S5日志项不是最新的,不能成为term3 的leader。

新leader会在S2, S3中诞生。

4.上个term的日志提交

首先试想这样一种场景:
在这里插入图片描述

在一个5节点集群中,term2时,S1是leader,此时日志项3已复制到S2,并且在复制到S3之前,S1宕机。

接着,S5发起投票,可以得到自己以及S3、S4的超过半数的投票,而成为leader。
即S5成为term3 的leader。

S5在term 3 内 提交日志项3、4、5,但都未能复制到其他节点,就宕机了。

这时,S1发起选举,S1可以得到自己、S2、S3、S4的投票,S1又成为 term 4的leader。

接着S1将日志项3复制到S3。此时日志项3已复制到超过半数节点。

S1在term4,只在本地提交了日志项4,接着宕机。

此时,S5发起投票,可以得到自己以及S2、S3、S4的投票。

S5成为term 5的leader,就会将S1、S2、S3的日志项覆盖掉。

也就是说,虽然日志项3被复制到了超过半数节点,是commited的日志,也有可能被覆盖掉。

如何解决这个问题呢?

为了解决这个问题,raft在日志项提交上增加了限制
,在提交之前term的日志项时,必须保证当前term新建的日志项已经复制到超过半数节点。这样,之前term的日志项才算真正提交的。

实际上,只有日志项4提交后,日志项3才是真正提交的。
即S1 成为term4 leader后,提交日志项4。
如图所示,
在这里插入图片描述

因为一旦日志项4提交后,S5就不可能成为term 5的leader,就不会出现日志被覆盖的情况。

5.参考

raft 论文

编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示