容错分布式一致性算法——totem(一)

版权声明:欢迎转载,转载请注明出处~ https://blog.csdn.net/zancijun1666/article/details/83512038

  第一次接触分布式一致性算法是通过totem,现在开始研究paxos和raft之类,后面也是会做笔记的,便先将totem算法先写下来,用于对比学习。
  totem协议,全称是The Totem Single-Ring Ordering and Membership Protocol,是一个基于令牌环的分布式一致性算法。一个令牌在集群节点之间传递,拿到令牌的节点才能够发消息,消息通过UDP广播发送。所以,totem只适合在局域网里的小集群使用,这种情况下,这个算法性能还算高的。从CAP来说,totem具有强一致性,但几乎没有分区容错性,在网络出现分区时,totem会脑裂,当网络恢复时,会造成消息丢失。所以我们集群的做法是网络有问题时禁止节点发送消息。
  现在来具体介绍这个协议,首先我们明确totem实现了什么:在多个节点组成的集群中,totem实现让一个节点发送消息,其它所有节点都能全部收到,并且有序的提交给上层应用,这里的环境和paxos一样是除拜占庭问题外的环境。为了方便表述,且totem使用令牌环,这里将一个集群也称作一个ring。下面是一张集群的状态图,每个节点都会经历以下状态。
totem状态机
  totem的节点有四个状态,也是组建集群的4个阶段。
Gather阶段:
  这个阶段用于每个节点向外界广播自己的存在并收集其它节点的存在
Commit阶段:
  这个阶段会产生一个代表节点,该节点向其它所有节点收集信息,并将收集的信息传递给其它所有节点,用于后续阶段
Recovery阶段:
  这个阶段用于新旧集群交替时,旧集群成员用新集群传递旧集群的消息,使旧集群成员达到所有节点消息全部有序提交到上层
Operational阶段:
  这个阶段是集群组建完成正常工作的状态,这个状态一个节点发送的消息其它节点都会全部有序提交给上层

  totem协议可以概括为三个部分,集群正常运行时候的THE TOTAL ORDERING PROTOCOL,operational状态就是运行这个协议;集群状态变化时的THE MEMBERSHIP PROTOCOL,gather、commit和operational状态包括在这个协议内;新旧集群交替时,旧集群消息恢复的 THE RECOVERY PROTOCOL,recovery状态就在这个协议内。

  先讲Operational状态的THE TOTAL ORDERING PROTOCOL,这个是组成集群后的正常运行时的状态,我们先设想它该具有怎样的功能,再看totem协议有些什么,这样就很好理解totem协议的每个字段和机制的作用了。首先,分发消息的功能是一定有的,消息是全部有序到达各个节点的,其次,作为一个强一致性的协议,节点fail或者网络出问题需要能够感知。

看下需要每个processor本地维护的变量:

变量 值的意义
my_token_seq 本processor最后获得token时的token_seq
my_aru 本processor收到my_aru序号以下的所有message
my_aru_count 本processor收到相同aru但aru不等于seq的token次数
new_message_queue 本processor产生的等待发送的消息队列。
received_message_queue 本processor收到的等待提交给application的消息队列
  • my_token_seq这个变量用于辨认收到的token是否重复了,例如网络不好的时候,token会进行重传。
  • my_aru主要和token中的记录的消息seq对比,确定是否本节点有消息没收到。
  • my_aru_count用于确定集群是否发生异常,如果aru多次相同且不等于seq,则说明集群网络出现问题或者集群发生整体消息丢失,会触发重组集群,后者一般不会出现。
  • new_message_queue是个缓存队列,当拿到令牌的时候,节点顺序发送这些消息。
  • received_message_queue也是个缓存队列,节点收到的消息先缓存在这里,当所有节点都收到连续到某个序号的消息后(token里的aru指示所有节点都收到的连续到的最大消息号),会将这里的消息提交给上层,并删除这些已提交的消息。

  有这些本地存储的变量,现在再看下节点间传些什么
消息类型1:Regular Message

变量 值的意义
sender_id 标记谁产生这个消息
ring_id 标记产生这个消息的ring,包含ring sequence number和representative’s identifier。
seq 消息序号
conf_id 0
contents 要发布到各个节点的内容
  • sender_id用来记录到底是哪个节点发出的消息,但在corosync实现中似乎没什么用,除了排查bug会用下之外。
  • rind_id用来标识ring,ring seq是顺序递增的,corosync的实现是每次+4, representative’s identifier是代表节点的标识,corosync的实现是代表节点ip。代表节点会在讲解commit状态的时候描述。
  • seq是在此ring中消息的序号,这个是集群内唯一且顺序递增的。
  • conf_id这个值在重组集群的时候会用到,在totem算法理解中不用太关注
  • contents这个是消息数据主体

消息类型2:Regular Token

变量 值的意义
type Regular
ring_id token所属的ring,包含ring sequence number和representative’s identifier
token_seq token序号
seq ring里消息的最大序号
aru (all-received-up-to) 所有processor都接收到小于或等于aru序号的消息
aru-id 记录将aru设置成比seq小的processor
rtr 请求重新传输列表。
  • type字段用于标记这个token是什么类型,主要有regular和commit类型,regular是operational和recovery状态会有的,在commit阶段的就是commit类型
  • ring_id字段和regular message的ring_id作用一致
  • token_seq是令牌的序号标识,这个序号单调递增,每经过一个节点增加1,用于认出重复的token
  • seq记录的是ring里最大的regular message的序号,这个值用于标记令牌里发的消息的最大编号,在每个节点收到这个值后可以对比获知自己缺了哪些消息,每个节点在持有令牌的时候才发消息,如果自己有发消息,则传递令牌到下一个节点的时候会更新这个字段。
  • aru这个值用于各个节点获知哪些消息是所有节点都获取到了的,当确认所有节点都获取到消息后,就开始提交到上层。当节点连续收到两次token的aru都大于某值时,就认为该序号及以前的消息被所有节点所接收。如果节点收到token,发现token里的aru值大于自己已连续获取的消息序号最大值,则将token里的aru修改成自己的aru值。并修改下面token里的aru-id字段,这样可以告诉下一个获取到token的节点自己缺了消息。
  • aru-id,节点在收到token时,如果自己已收到的包没有达到token上记录的seq那么多(aru比seq小),则设置token的aru字段并修改aru-id为本节点的标识符。当本节点收到aru达到seq时,则判断aru-id是否自己,如果是自己则清除这个值。
  • rtr,当节点发现本节点收到的包比token上seq记录的序号少时,就在token的rtr上记录缺少的包。当token在其它节点循环时,其它节点如果发现本地有rtr上标记的包,就广播该包,并清除rtr上的对于记录,这样就可以实现信息共享了

  从上述这些维护的变量以及消息内容来说,可以基本的推断totem协议在operational状态是怎么工作的了,下面具体看下协议内容:
  协议在使用状态是这样的,令牌在每个节点循环,令牌是Regular Token描述的,节点拿到令牌之后才能发送消息,消息是Regular Message结构体描述的。节点在拿到令牌后做这么些事:

  • 取消token 重传定时器
  • 查看令牌rtr是否有消息记录,如果本节点有那些消息则广播这些消息,并从rtr上删除这些消息
  • 对比my_aru和令牌的seq,查看是否有消息本节点没有收到,如果有则设置令牌上的aru和rtr以及aru_id
  • 如果new_message_queue有消息,则广播消息,并修改令牌中的seq
  • 如果两次token中的aru的值都大于某个值m,则向上提交序号大于m的消息
  • 发送令牌给下一个节点
  • 启动token重传定时器,再次收到token或者regular message的时候取消

  token有重传机制,用于防止消息丢失和发现网络问题重组集群,本地变量my_aru和token里的aru和seq用于确认所有节点都收到消息,aru_id和rtr用于重传消息给某节点。可以看到totem的每个变量设置目的都是很明确易懂的。至此,我想读者应该明白totoem的operational状态是怎么运转的了。

参考:
https://download.csdn.net/download/zancijun1666/10715783

猜你喜欢

转载自blog.csdn.net/zancijun1666/article/details/83512038