在分布式系统的设计中,要解决的最主要问题之一就是单点故障问题(single point of failure (SPOF) )。为了能在某个节点宕机后,系统仍然具备正常工作的能力,通常需要对节点部署多个副本,互为主备,通过选举协议在多副本中挑选出主副本,并在主副本发生故障后通过选举协议自动切换至备副本。
主副本称为 Leader,备副本称为 Follower。
在分布式系统中,一个工作良好的选举协议应当符合两点预期:
正确性
即当一个副本认为自己是 Leader 的时候,不应该有其他副本同时也认为自己是 Leader,在集群中同时有两个副本认为自己是 Leader 的情况称为"脑裂",如 Raft 协议中的选举机制,通过保证为每个 Term 只分配一个 Leader 来避免脑裂,但是原生 Raft 中同一时刻可能有多个副本认为自己是 Leader(尽管它们分管不同的 Term,且更小的 Term 的主副本已经失效但是其不自知),使用原生的 Raft 协议必须读取多数派的内容来保证读取到的数据最新,OceanBase 数据库通过 Lease 机制避免对多数派的访问,确保在任意的时间点上只有一个副本能认为自己是 Leader。
活性
即任意时刻,当 Leader 宕机时,只要集群中仍然有多数派的副本存活,那么在有限的时间内,存活副本中应当有副本能够成为 Leader。
在满足正确性和活性的基础上,OceanBase 数据库的选举协议还提供了优先级机制与切主机制,优先级机制在当前没有 Leader 的情况下在当前可当选 Leader 的多个副本中,选择其中优先级最高的副本称为 Leader;切主机制在当前有 Leader 的情况下可以无缝将 Leader 切换至指定副本。
假设与容错
OceanBase 数据库假定其运行的物理环境满足一定的约束:
任意两台机器间的单程网络延迟应当满足小于某个上限值,称为 MAX_TST。
集群中所有机器的时钟与 NTP Server 进行同步,且与 NTP Server 的时钟偏差小于给定的最大偏差,称为 MAX_DELAY。
目前 OceanBase 数据库的系统参数为,MAX_TST = 200ms,MAX_DELAY = 100ms。
注意到,若任意机器与 NTP 服务器的时钟偏差不超过 100ms,则任意两台机器间的时钟偏差不超过 200ms。
当时钟偏差和消息延迟的假设不满足时,将发生无主,但是由于安全接收窗口的检查,无论是否满足环境约束,选举协议的正确性都是可以保证的。
优先级
在选举的第一阶段,所有副本都会在同一时刻广播自己优先级,这将使得每个副本都具备足够的信息比较所有副本的优劣,集中投票给同一副本,这一方面避免了选举的分票,另一方面也让选举协议的结果更符合预期,更好预测。
选举优先级是一系列字段的集合,这些字段都有各自的比较规则,这些字段优先级从高到低包括:
成员列表版本号(越大优先级越高)
副本所在的 region 的属性(primary region > 非 primary region)
内存满状态(未满 > 已满)
程序初始化状态(已初始化 > 未初始化)
选举黑名单状态(不在黑名单 > 在黑名单)
Rebuild 状态 (不需要 Rebuild > 需要 Rebuild)
数据盘状态 (数据盘无错误 > 数据盘有错误)
租户内存满状态 (租户内存未满 > 租户内存满)
CLOG 盘状态 (CLOG 盘无错误 > CLOG 盘有错误)
副本类型(F 副本 > 非 F 副本)
CLOG 盘满状态 (CLOG 盘未满 > CLOG 盘满)
CLOG 日志数量 (越多优先级越高)
切主
用户可以指定分区 Leader,RS 会给对应的分区发消息以完成 Leader 的变更,这种变更通常是很快的。
用户也可以变更 primary region,RS 将指挥分区将 Leader 切换至新的 primary region 上。
当用户开启 enable_auto_leader_switch 选项后,RS 会在 primary zone 中使用切主的方式平滑的分散 leader 的分布。




