文章20 | 阅读 8352 | 点赞0
Consul使用Consensus协议提供一致性(Consistency)——CAP定义的一致性。Consensus协议是基于"Raft:In search of an Understandable Consensus Algorithm"实现的。
本节主要讲解consul内部技术细节,使用consul不需要必须了解这些细节的。这些文章是为那些不愿意深入源代码但是希望技术细节的人准备的。
Raft是一种基于Paxos的Consensus算法。相比于Paxos,Raft设计采用了较少的状态,并且是一种更简单、更易于理解的算法。
在讨论Raft前,需要了解一些术语:
Log – Raft系统的基本的工作但是与Log entry。一致性相关的问题可以分解为replicated log。一个log是一个顺序的条目列表(entrylist)。如果所有的成员均同意log的entry和顺序,那么则认为log是一致的。
FSM –有限状态机,有限个状态以及在这些状态之间的转移和动作等行为的数学模型。新log的应用,FSM会发生状态转换,相同的LOG序列的应用必须导致相同的状态,这意味着行为必须是确定性的。
Peer set –参与log replication的成员组成了Peer set,对于Consul而言,所有的server节点均属于本地数据中心的peer set。
Quorum –(汉语可以翻译为法定人数)peer set中成员的最大数。对于N的set,quorum要求至少有(N/2)+1成员。例如,peer set有5个Server节点,就需要至少3个节点才能形成quorum。无论什么原因,只要quorum是无效的,那么cluster就会变为unavailable,并且不会再有log提交。
CommittedEntry –当日志持久地存储在quorum个节点后才能成为commited entry。一旦entry被提交,它才能被使用。
Leader -在任何给定的时间,peer set选举一个节点作为Leader。当logcommited时,Leader负责新entry 处理、复制到Followers、管理条目。
Raft是一个复杂的协议,这里不会详细讨论细节,将不会在这里详细介绍(如果希望更全面的了解,可以参阅Paper)。
本文会从框架上来描述Raft,并构建一个智慧模型。
Raft节点总会是Follower、candidate、Leader三个状态之一。所有的节点最初开始作为一个Follower。在这种状态下,节点可以接受来自Leader的log enties或投票。如果一段时间内没有收到entries,节点自我提升到candidate状态。在candidate状态,节点请求来自peer节点的投票。如果一个candidate节点获得的票数超过quorum,然后该节点会晋升为Leader。Leader必须接受新的日志条目,并复制到所有其他的Follower。此外,如果stale read(过时的读取)是不可接受的,所有的查询也必须在Leader节点执行。
一旦集群有了Leader,并且Leader能够接受新的日志条目。Client节点可以请求Leader追加新的日志条目(从Raft角度看,日志是一个不透明的二进制blob)。然后,Leader将entry写入持久存储,并尝试复制到quorum个Follower节点。一旦logentry被认为commited,那么它就可以应用于FSM。FSM是专用的;在Consul中,我们使用BoltDB维护集群状态。
让Replicatedlog无限制的增加,显然是不可取的方式。Raft提供了一种机制——压缩当前状态的快照和日志。因为FSM是抽象的,重放过去一段时间的旧日志来恢复FSM的状态,必然导致相同的状态。因此,在一个时间点,当Raft采集到FSM状态后,会删除转换到该状态所使用到的所有的旧日志,无需用户干预自动执行,可以防止无限制的磁盘使用,同时也减少了重放日志时间。使用boltdb的优点是,它允许Consul继续接受新的交易,即使旧状态正在创建快照,避免产生任何可用性的问题。
只要有quorum个节点有效,Consensus是容错的。如果有效节点数无法达到的quorum,那么不可能处理log entry或维护成员关系。例如,假设只有2个peer:A和B。quorum也是2,这意味着这两个节点必须同意提交日志条目。如果A或B有一个失败,现在是不可能满足quorum个节点有效的条件。这意味着群集无法添加或删除节点或提交任何额外的日志条目。这样的结果就是集群不可用。这时,需要手动干预,删除A或B,然后以引导模式重新启动剩余节点。
3个节点的Raft集群可以容忍1个节点故障,5节点的集群可以容忍2个节点的故障。因此,Consul推荐部署包含3或5个Server节点的数据中心。这样可以最大限度地提高可用性,而不会大大牺牲性能。下面的表格总结了集群节点数目与容忍的故障节点数目:
| <br>Servers<br> | <br>Quorum Size<br> | <br>Failure Tolerance<br> |
| <br>1<br> | <br>1<br> | <br>0<br> |
| <br>2<br> | <br>2<br> | <br>0<br> |
| <br>3<br> | <br>2<br> | <br>1<br> |
| <br>4<br> | <br>3<br> | <br>1<br> |
| <br>5<br> | <br>3<br> | <br>2<br> |
| <br>6<br> | <br>4<br> | <br>2<br> |
| <br>7<br> | <br>4<br> | <br>3<br> |
在性能方面,对比Raft与Paxos。假设都存在稳定的Leader,提交一个日志条目需要写入到quorum个节点。因此,性能是由磁盘I / O和网络延迟的限制。虽然Consul不是以设计高吞吐量的写系统为目标,能否处理数以百千计的事务还是取决于网络和硬件配置。
只有ConsulServer节点参与Raft、是peer set的一员。所有的Client节点只是转发请求到Server。这种设计的考虑是,当更多的成员加入到peer set中时,quorum的规模也会增加。可能会导致性能问题——等待quorum个节点 log entry。
** 启动Consul时,单个consul节点需要以bootstrap模式运行,该模式运行自我选举为leader。一旦Leader被选出来,其他Server可以添加Peer set中,保持一致性和安全性。最终,一旦一些Server添加到集群,bootstrap模式就需要禁用。**
因为所有Server都是Peer set中的医院,它们都知道谁是Leader。当一个RPC请求到达某个非Leader Server节点,请求就会被转发到Leader。如果RPC是一种query类型,这意味着它是只读的,Leader会基于FSM当前生成相应的结果,如果RPC是一种transaction类型,即修改状态,Leader产生一个新的日志条目,并基于Raft算法进行管理。一旦日志条目应用于有限状态机,transaction完成。
由于Raft的副本性质,性能对网络延迟是非常敏感的。为此,每个数据中心选择独立的Leader和维护一个不相交的peer set。数据按照数据中心进行划分,所以每个Leader只负责在相应数据中心的数据。当接收到一个远程数据中心的请求时,请求会被转发到相应的Leader。这种设计在不牺牲一致性的情况实现较低延迟交易和更高的可用性。
虽然所有日志副本的写入都是基于Raft,读取更灵活。但为了支持开发人员可能需要的各种权衡,Consul支持3种不同的一致性模式。
三种读模式是:
•Default-Raft采用Leader租赁模式,提供了一个时间窗口,在该时间段内,Leader角色是稳定的。但是,如果Leader从Peers set分裂出去,新的Leader就可能选举出来,而旧Leader持有租赁。这意味着有2个leader节点。因为旧Leader不能提交新日志,就没有脑裂的风险。然而,如果旧Leader执行任何读取操作,其读取到的结果就可能是陈旧的。Default一致性模式只依赖于Leader租赁,Client可能使用过期的数据。之所以这么权衡,因为读取是快速的,通常是采用强一致性模式,比较难以触发的情。并且时间窗口也是有界的,时间到了,leader也会下台。
•consistent,这种模式是无条件一致性。它要求leader必须与quorum个peer校验,虽然它仍然是Leader。这将引入额外的节点轮训,增加了延迟。采用一致性读取,会导致额外的轮训开销。
•stale-这种模式允许在任何Server节点执行读取操作,无论它是不是Leader。这意味着可能读取到旧的数据,但一般而言,速度与leader相比差距在50毫秒内。这种方式,读取速度是非常快的,但可能是旧的数据。这种模式下,即使没有Leader,一样可以相应读取操作。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://younger.blog.csdn.net/article/details/52652979
内容来源于网络,如有侵权,请联系作者删除!