Raft 集群成员变更、日志压缩、客户端交互

集群成员变更

在集群服务器发生变化时,不能一次性的把所有的服务器配置信息从老的替换为新的,因为,每台服务器的替换进度是不一样的,可能会导致出现双主的情况,如下图:

如上图,Server 1和Server 2可能以 Cold 配置选出一个主,而Server 3,Server 4和Server 5可能以 Cnew 选出另外一个主,导致出现双主。

raft使用两阶段的过程来完成上述转换:

  • 第一阶段,新老配置都存在,称为joint consensus
  • 第二阶段,替换成新配置

    • 领导者首先创建Cold,new的log entry,然后提交(保证大多数的old和大多数的new都接收到该log entry);

    • 领导者创建Cnew的log entry,然后提交,保证大多数的new都接收到了该log entry。

这个过程中,有几个问题需要考虑。

  • 新加入的server一开始没有存储任何的log entry,当它们加入到集群中,可能有很长一段时间在追加日志的过程中,导致配置变更的log entry一直无法提交

Raft为此新增了一个阶段,此阶段新的server不作为选举的server,但是会从leader接受日志,当新加的server追上leader时,才开始做配置变更。

  • 原来的主可能不在新的配置中

在这种场景下,原来的主在提交了Cnew log entry(计算日志副本个数时,不包含自己)后,会变成follower状态。

  • 移除的server可能会干扰新的集群

移除的server不会受到新的leader的心跳,从而导致它们election timeout,然后重新开始选举,这会导致新的leader变成follower状态。Raft的解决方案是,当一台server接收到选举RPC时,如果此次接收到的时间跟leader发的心跳的时间间隔不超过最小的electionTimeout,则会拒绝掉此次选举。这个不会影响正常的选举过程,因为,每个server会在最小electionTimeout后发起选举,而可以避免老的server的干扰。

日志压缩

Raft的日志会随着处理客户端请求数量的增多而不断增大,在实际系统中,日志不可能会无限地增长,原因如下:

  • 占用的存储空间随着日志增多而增加
  • 日志越多,server当掉重启时需要回放的时间就越长

因此,需要定期地清理日志,Raft采用最简单的快照方法。对系统当前做快照时,会把当前状态持久化到存储中,然后到快照点的日志项都可以被删除。

Raft算法中每个服务器单独地做快照,即把当前状态机的状态写入到存储中(状态机中的状态都是已提交的log entry回放出来的)。除了状态机的状态外,Raft快照中还需要一些元数据信息,包括如下:

  • 快照中包含的最后一个日志条目的索引值和任期号,记录这些信息的目的是为了使得AppendEntriesRPC的一致性检查能通过,因为,在复制紧跟着快照后的日志条目时,AppendEntries RPC带上需要复制的日志条目前一个日志条目的(索引值,任期号),即快照的最后一个日志条目的(索引值,任期号),因此,快照中需要记录最后一个日志条目的(索引值,任期号)

  • 为了支持集群成员变更,快照中保存的元数据还会存储集群最新的配置信息。

当服务器完成快照后,可以删除快照最后一个日志条目及其之前所有的日志条目,以及之前的快照。

虽然每个服务器是独立地做快照的,但是也有可能存在需要领导者向跟随者发送整个快照的情况,例如,一个跟随者的日志处于领导者的最近一次快照之前,恰好领导者做完快照之后把其快照中的日志条目都删除了,这时,领导者就无法通过发送日志条目来同步了,只能通过发送完整快照。

领导者通过 InstallSnapshot RPC来完成发送快照的功能,跟随者收到此RPC后,根据不同情况会有不同的处理:

当follower中缺失快照中的日志时

  • follower会删除掉其上所有日志,并清空状态机

当follower中拥有快照中所有的日志时

  • follower会删掉快照所覆盖的log entry,但快照后所有日志都保留。备注:这里论文中没有提是否还是从leader接受快照,个人觉得follower可以自己做快照,并拒绝掉leader发快照的RPC请求

对于Raft快照,关于性能需要考虑的点有:

  • server何时做快照,太频繁地做快照会浪费磁盘I/O;太不频繁会导致server当掉后回放时间增加,可能的方案为当日志大小到一定空间时,开始快照。备注:如果所有server做快照的阈值空间都是一样的,那么快照点也不一定相同,因为,当server检测到日志超过大小,到其真正开始做快照中间还存在时间间隔,每个server的间隔可能不一样

  • 写快照花费的时间很长,不能让其影响正常的操作。可以采用copy-on-write操作,例如linux的fork

客户端交互

Raft 中的客户端发送所有请求给领导人。当客户端启动的时候,他会随机挑选一个服务器进行通信。

  • 如果选择的服务器是领导者,那么客户端会把请求发到该服务器上

  • 如果选择的服务器不是领导者,该服务器会把领导者的地址告诉给客户端,后续客户端会把请求发给该领导者

  • 如果此时没有领导者,那么客户端会timeout,客户端会重试其他服务器,直到找到领导者

Raft 的目标是要实现线性化语义(每一次操作立即执行,只执行一次,在他调用和收到回复之间)。但是,如上述,Raft 是可以执行同一条命令多次的:例如,如果领导人在提交了这条日志之后,但是在响应客户端之前崩溃了,那么客户端会和新的领导人重试这条指令,导致这条命令就被再次执行了。解决方案就是客户端对于每一条指令都赋予一个唯一的序列号。然后,状态机跟踪每条指令最新的序列号和相应的响应。如果接收到一条指令,它的序列号已经被执行了,那么就立即返回结果,而不重新执行指令。

只读的请求可以不写log就能执行,但是它有可能返回过期的数据,有如下场景:

领导人响应客户端请求时可能已经被新的领导人作废了,但是他还不知道

Raft 需要使用两个额外的措施在不使用日志的情况下保证这一点。

  • 首先,领导人必须有关于被提交日志的最新信息。领导人完全特性保证了领导人一定拥有所有已经被提交的日志条目,但是在他任期开始的时候,他可能不知道那些是已经被提交的。为了知道这些信息,他需要在他的任期里提交一条日志条目。Raft 中通过领导人在任期开始的时候提交一个空白的没有任何操作的日志条目到日志中去来实现。

  • 第二,领导人在处理只读的请求之前必须检查自己是否已经被废黜了(他自己的信息已经变脏了如果一个更新的领导人被选举出来)。Raft 中通过让领导人在响应只读请求之前,先和集群中的大多数节点交换一次心跳信息来处理这个问题。可选的,领导人可以依赖心跳机制来实现一种租约的机制,但是这种方法依赖时间来保证安全性(假设时间误差是有界的)。

Raft 集群成员变更、日志压缩、客户端交互相关推荐

  1. raft中集群成员变更

    文章目录 1. raft集群变更再学习 2. 单阶段过度的风险分析 3. 两阶段过度的完整性分析 4. 集群变更时可能存在的其他问题 1. 新加入的节点没有日志 2. 集群领导人可能需要下线 3. 从 ...

  2. 2022-03-01 快速搭建raft集群

    目录 摘要: raft测试代码: raft-grpc-example: 编译: raftadmin: 编译: 快速组建raft集群: 一. 生成需要的文件目录 二. 分别启动一个bootstrap节点 ...

  3. 【基于容器的部署、扩展和管理】3.6 集群监控和日志收集

    往期回顾: 第一章:[云原生概念和技术] 第二章:[容器化应用程序设计和开发] 第三章:[3.1 容器编排系统和Kubernetes集群的构建] 第三章:[3.2 基于容器的应用程序部署和升级] 第三 ...

  4. ORACLE集群日志收集,【RAC】Oracle RAC集群环境下日志文件结构

    在Oracle RAC环境中,对集群中的日志的定期检查是必不可少的.通过查看集群日志,可以早期定位集群环境中出现的问题,以便将问题消灭在萌芽状态.简单介绍一下有关Oracle集群环境中日志的结构,方便 ...

  5. centos7 部署glusterfs集群,服务端和客户端演示

    centos7 部署glusterfs集群,服务端和客户端演示 说明 glusterfs 分布式文件服务,详细可以百度 官网文档: https://docs.gluster.org/en/latest ...

  6. Nginx之反向代理、日志格式、集群、缓存、压缩、URl 重写,读写分离配置

    location的模式匹配按照优先级由低到高有以下四种: Nginx作为一个优秀的Web服务器,不仅在处理静态内容上比Apache优秀,还经常被用来做反向代理服务器,且支持缓存,URL重写,自定义格式 ...

  7. etcd v2文档(2) -- 客户端http请求管理集群成员api

    为什么80%的码农都做不了架构师?>>>    列出成员 返回一个HTTP 200 OK响应代码和所有成员在etcd集群中的表示. Request GET /v2/members H ...

  8. GBase 8a管理集群gcware的日志-vote leader、flower、candidate部分

    环境 2节点集群 [gbase@gbase_rh7_001 log]$ gcadmin CLUSTER STATE: ACTIVE VIRTUAL CLUSTER MODE: NORMAL====== ...

  9. 【Kafka】测试集群中Broker故障对客户端的影响

    本文主要测试Kafka集群中Broker节点故障对客户端的影响. 集群信息:4个broker.topic:100+(每个topic30个partition).集群加密方式:plaintext.存储:c ...

最新文章

  1. 有理有据:一篇来自前端同学对后端接口的吐槽!
  2. 使用阿基米德螺线进行数据可视化
  3. C#开源资源大汇总(2)
  4. bat 调用class文件_Logback 配置文件这么写,TPS 提高 10 倍!
  5. MySQL如何执行关联查询
  6. 2021-08-10小米盒子3增强版挂U盘刷v1.46版历程
  7. 清理谷歌浏览器注册表_Win10系统下注册表chrome残留无法删除
  8. 《全网首发》基于SEIR(SIR)对新冠肺炎的分析和预测
  9. FB_LLC 死区时间计算(保证ZVS)
  10. DELL Inspiron_620/620s网卡驱动
  11. 关于compose的
  12. 电脑一键还原,电脑怎么一键还原系统(手把手教你电脑一键还原)
  13. Python灰帽子——黑客与逆向工程师的Python之道
  14. 《Semi-Supervised Semantic Segmentation with Cross-Consistency Training》 2020CVPR 论文阅读
  15. element-ui中el-cascader级联选择器多选判断是否是全选
  16. 国外对国产防火墙的评价(排名)
  17. linux资源不可用,资源暂时不可用(Resource temporarily unavailable)
  18. 崇州 鸡冠山 白塔湖 九龙沟 罨画池 陆游祠{组图及介绍}
  19. Unity 自动创建材质球工具
  20. zigbee 源码 02-光敏传感器

热门文章

  1. 如果机房的线路老化了要怎么做才对?
  2. python怎么添加列_如何将列添加到DataFrame列?添加新列详细解释————
  3. 成功解决ERROR: Could not find a version that satisfies the requirement xgboost (from versions: none) ERR
  4. AI:2020年7月10日世界人工智能大会WAIC青少年人工智能创新发展论坛《人工智能从娃娃抓起》
  5. DL之ShuffleNetV2:ShuffleNetV2算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
  6. Dataset之WebVision:WebVision数据集简介、下载、使用方法之详细攻略
  7. BlockChain:《Blockchain Gate》听课笔记——区块链的1.0架构 VS 区块链3.0架构+个人理解
  8. TF:基于CNN(2+1)实现MNIST手写数字图片识别准确率提高到99%
  9. 成功解决 ModuleNotFoundError: No module named ‘PyQt5.sip‘
  10. docker 如何删除<none>镜像