一、ONOS的一致性保障
ONOS主要包括两类一致性机制,最终一致性和强一致性,最终一致性采用乐观异步复制和基于Gossip的熵减方式来实现,乐观异步复制可以高效的实现最终一致,但是一旦集群中发生节点脱离集群或者重启的情况整体集群就会出现越来越失序的现象,基于Gossip的熵减方案就是为了解决此类问题,集群中的节点定期(通常间隔三到五秒)地随机选择一个节点进行数据同步,大多数情况下,熵减互动是平常的,因为每个控制器已经知道发生在网络中的每一个事件。 但是当一个控制器状态稍微漂移时,这个机制很快就会检测到这个状态,并使控制器重新同步。 这种方法还具有快速将新加入的控制器和其他的控制器进行同步的好处。 新加入的控制器与现有控制器之间的***次熵减互动将很快实现节点同步,而不需要单独的备份/发现机制。
在动态扩容的情况下,动态节点的加入会对最终一致性产生影响,表现为新的节点加入集群,在和其他节点的熵减交互以及乐观复制中最终和整体集群达到一致。这部分涉及的子系统包括Device和Link子系统。
而Device,Link子系统也会影响到Topo子系统,所以在进行节点动态扩容时,新加入节点在实现最终一致的过程中如果不承载业务的话影响较小。
强一致性的保障通过Raft算法来实现,ONOS考虑到容错和性能的通盘考虑,选择了分区机制和备份冗余机制。
分区机制是指ONOS对任意一个支持强一致性的分布式原语(主要包括其分布式数据结构)支持分区机制,而在每一个分区中支持多个节点之间的备份冗余,实现了CAP理论的折衷性考虑。
二、ONOS逻辑时钟
在分布式系统中时钟是个重要的概念,ONOS选取了以MasterShip Term和本地事件序列号的方式来进行统计。其理论依据如下:
- 网络控制器的控制离不开设备,所有的网络事件都是最终都能关联到设备上
- MasterShipTerm是全局强一致的,依赖这个数据做时钟的可靠性高
- 控制器依赖从设备收上来的信息来发出网络事件,而真正抛出事件的只有Master,Master维护着对应设备上报事件的序列号,在每一个Term周期内从0开始单调递增
三、动态扩容对强一致性的影响
当前ONOS大部分子系统都采用的是强一致性的方式,包括:FlowRule, Host, MasterShip等,其中MasterShip是整体集群数的强一致,其他子系统是基于Partition内部节点的强一致。所以ONOS集群的宕机风险和Partition Member数量有关,如果Partition Member只有三个节点,那么两台设备宕机就会造成系统问题。
在节点动态加入集群的场景下,***的问题是要防止出现脑裂,所谓脑裂就是一个集群中同时出现两个Leader的场景,在集群节点减少的情况下不会出现,但是在集群添加节点时会出现这种场景,如下图所示:
在上图所示的场景之下,假如新的Server先以新配置启动,而旧的Server逐步以新配置运行,此时会存在新配置的大多数和旧配置的大多数共存的情况,操作不慎会导致集群存在两个Leader进而脑裂的情况。
ONOS的raft算法采用Copycat实现,其支持动态节点的加入,但是这个方法不同于Raft论文中提到的两阶段添加的方案,而是采用了单节点添加方案来避免出现脑裂的情况,这样使得方案更简单但是相对操作会麻烦一些。另外在新加入节点开始进行数据同步时,业务要尽量避免写入。以免影响读写性能。
四、ONOS带状态重启
带状态重启也是生产环境中非常重要的一点。ONOS大部分分布式数据结构都是支持持久化的,部分不支持的主要是最终一致性数据结构。 这其中ECMap必须配置持久性选项才能将条目写入磁盘,否则在集群关闭时会丢失。
但是大多数分布式原语(强一致性)使用了Raft集群,并且它们是持久化的。 ConsistentMap,ConsistentTreeMap,DocumentTree,DistributedSet,LeaderElector以及这些基元的所有Async *版本都使用单个Raft分区或所有Raft分区。 这些原语有效地由持久的复制日志支持,该日志将从该/ data目录中读取,并在重新启动群集时重播。