openGauss的DCF组件详解

  • 组件介绍
  • 功能介绍
  • 模块介绍
  • 代码仓库
  • 数据库对接

目录


1 DCF 组件介绍

DCF(分布式共识框架)目标:构建稳定可靠、低时延、高吞吐的一致性数据复制组件。

这一技术组件需要承载以下工作:

  • 副本高可用
    • 主备之间备份
    • 容灾性自动/手动升主降备
    • 跨AZ(可用区)的多副本复制
    • 多日志流的复制
  • 简化集群管理
    • 集群状态发布
    • 集群配置管理
    • 委托选主
    • 分布式全局锁

1.1 需求背景与优势

传统主备集群管理常采用第三方仲裁,如采用Etcd集群实现主备节点间的切换:

第三方仲裁管理


这样的第三方仲裁会出现一些问题,如脑裂。有可能第三方仲裁认为节点故障,但实际上没有,此时会出现脑裂的情况。此外,还会出现因中间状态而出现的日志分叉的情况。

自仲裁管理


openGauss引入DCF自仲裁,DCF作为一个动态库集成在openGauss存储引擎中,在DB内核中自检测。DCF通过一致性协议,协商哪一节点作为主节点,以保证在任何情况下都不会出现脑裂既双主的情况,也不会出现日志分叉的情况。并且相比传统主备集群管理,大大简化了故障检测环节,进而减小集群RTO(容许服务中断的时间长度)。

自仲裁具有很多优势:

自终裁优势


并且在openGauss中,同过解耦使得DCF作为一个独立模块,既降低了复杂度,又使得后续的优化更方便。


1.2 一致性协议

一致性协议


DCF组件采用Paxos协议。当前被广泛采用的一致性协议还是Paxos族协议,Paxos算法在这些年已经经过了很多代演进。

1.2.1 两阶段Paxos


1.2.2 Multi-Paxos


在经典Paxos基础上添加租约机制,维持Leader节点状态。


1.2.3 Raft


在Multi-Paxos上进一步做了简化,更容易实现可靠性。

1.2.4 Paxos演进趋势

Paxos的演进


不同的Paxos算法都是在经典Paxos基础上,根据业务的情况选择了不同的侧重点。

DCF的目标是做一个适用于数据库的一致性日志复制组件。


2 功能介绍

对照数据库中想实现的一些特性,总结出以下想实现的功能:



设计的DCF为一个独立的组件,与内核解耦,最终实现一个位于底层的Paxos日志复制的共识框架,使得DCF不仅可以用在内核中,还可以用于集群管理等地方。DCF通过对节点进行多种角色的分类,使得集群管理更加灵活,降低容灾、数据备份等过程中的成本。

关键设计:

  • 支持自选主
  • 支持异步多线程框架和无锁cache设计
  • 支持多级batch. pipeline操作, 以及日志压缩能力V支持日志多流多复制
  • 不同分区主备副本可以在同-节点,方便实现负载均衡和异地多活
  • 基于网络带宽及网络时延自动探测的流控算法
  • 支持batch size、pipeline并发数自适应调整, 提升系统最大吞吐量

openGauss引入基于Paxos协议的DCF组件,能够保证数据一致性的同时,在高可用方面得到极大增强,主要包括:

  • 通过自仲裁、多数派选主能力摆脱第三方仲裁组件,极大缩短RTO时间,且可预防任何故障下的脑裂双主
  • 基于Paxos协议拓展的多样化节点角色,能够提供节点同步同异步混合部署等多种集群部署方式
  • 高性能、低时延的复制能力,使得openGauss在高可用方面得到极大增强的同时,还提升了主备节点间日志复制效率,提升系统最大吞吐能力

3 模块介绍

DCF模块


DCF模块划分如上图所示,作为一个动态库集成到数据库内核中。

  • interface:DCF通过interface接口层与数据库日志模块对接,提供读写等接口。flash刷盘的时候,数据库调DCF的interface接口写入,达成共识后,DCF会异步的通知上层写入成功。
  • metadata:元数据管理,定义集群节点信息,如IP端口,角色类型,选举超时时间等。
  • election:负责主节点的选举、心跳维持、状态发布。
  • replication:推进日志的分发并达成一致。
  • storage:负责日志数据的持久化。
  • communication:提供节点间的数据通信能力(TCP/UDP)。
  • Base:提供基础能力,如线程、日志、锁、队列等。

Gitee上可以查到DCF仓库


3.1 选举流程

DCF选举流程


preVote优化:

  • 为防止网络断连导致节点频繁发起选主请求,term持续增加
  • 在Follower变为Candidate前加入pre-candidate状态,发起term不变的预选举流程,成功后才将term++发起正式选主流程

Lease优化:

  • Leader与多数派断连主动降备,防止事实双主
  • 在lease时间内不响应term更高的选主消息

DCF在Paxos上增添了预选举环节,增加一次探测,当与大多数节点通信正常时才会发起选举,获得大多数节点的投票后当选为主节点,然后所有Follower跟随主节点做日志的同步。

DCF节点类型


选举核心之一是多数派原则,通过逻辑推理可以证明数据一定不会丢,因为无论是当选还是日志推进,多数派总是重叠的,以保证数据不丢失。


3.2 主机异常的处理

主机异常


  1. 网络异常或节点宕机,导致Leader心跳停止,日志复制停止。
  2. Follower检测到心跳超时, 转换为candidate, 发起新任期选举
  3. Follower若接收到其他节 点发起的选举,则判断任期和日志长度,确定是否投票给他
  4. candidate若得到超过半数的选票,则成为leader
  5. 新leader开始将自 己的日志发送给其他follower
  6. Follower接收新leader来的日志信息,判断日志是否跟自己连续匹配,连续匹配则接受。若不连续则返回,leader重新发送前段日志;若term不匹配,则将新leader的日志覆盖到原来的位置,并将后面的日志truncate掉

3.3 网络分区的处理

网络分区


  1. 集群网络异常分区,分裂出两个小集群
  2. 一个集群存在一个原leader, 新集群选举一个新leader, 任期增1
  3. 原leader也能接受写请求进行写入操作,但是无法达成大多数一致,导致无法提交
  4. 新leader也能接受写请求进行写入操作,能够达成一致,进行日志提交脑裂消失之后,由于原leader的term比较旧,会切换成follower
  5. 新leader的日 志复制给就leader,将就leader未提交日志覆盖

主机异常和网络分区都是每个自己检测的,所以节点的状态切换是根据自身的状态,不需要第三方去通知节点状态变更。


3.4 复制流程

复制流程


client thread指的是xlog中负责落盘的线程,通过调DCF的write接口,把数据写到buffer队列里面,写完后无阻塞立即返回。当本次写入得到大多认可后,会异步的write callback。而buffer里的数据会经过一系列的复制流水线,经过组包发送给备机。备机收到数据包后会回调Replay callback通知数据库内核,然后将数据拷贝到xlog日志里面。

异步流水


异步流水线

  • 日志采用全异步进行发送,不采用一问一答同步方式,提高系统整体吞吐量
  • Leader发送完一批log之后,直接更新next index,下次发送从这个点持续发送,不等follower响应回来;
  • Follower等落盘线程写完一批log之后,将最新的落盘match_index发送给leader,持续反馈最新的落盘index;
  • Leader通过这个来更新各节点的最新match_index,推进commit_index;

数据合并&压缩

  • 通信模块将包按大小进行压缩发送,减少网络带宽;
  • 根据发送队列情况自动合并数据包;

批量并行落盘

  • 应用端调用API write接口,写入内存buffer就返回,不阻塞应用其他流程处理,批量写盘和批量发送,日志到buffer之后,并行的将日志落入本地磁盘和发送到follower节点

多日志流

  • 支持DN粒度和分区粒度日志分组能力

吞吐量测试


吞吐量随时间变化平滑,平且相比同类产品吞吐量有提升。


4 代码仓库

DCF作者在Gitee上建有代码仓库,DCF编译后在数据库中以动态库的形式存在,内核通过 DCF/src/interface/dcf_interface.h 文件调用DCF的能力,那么打开dcf_interface.h看一下几个最核心的接口:

  • dcf_start:
    启动DCF模块,内核调用 dcf_start 将模块拉起。
  • dcf_write:
    拉起后调用 dcf_write 做数据写,DCF支持多日志流,但目前鸿蒙gauss里面只需要用一份日志。其中,通过 key 标识哪一份数据得到了承认,index 则标识着序列中的第几个数据得到了承认。
  • dcf_read:
    dcf_read 方法可以根据 dcf_write 方法中的 index 关键字读取DCF中对应的数据。
  • dcf_start:
    停止DCF模块。

使用步骤:

  1. 参数设置:设置buffer大小、压缩参数、心跳超时时间等
  2. 注册回调函数:leader方 日志达成一致的回调函数、follower apply/replay回调函数、身份变更通知回调函数
  3. 初始化启动:初始化模块,启动各线程
  4. 写入log
  5. 读取已存储的log
  6. 查询集群状态

5 数据库对接

数据库对接


数据库参数配置:

  • enable_ dcf = on
  • dcf_ node_ id = 3
  • dcf_ data_ path = ‘/dcf_ perf_ 03/px01/cluster/data/dn1/dcf_ _data’
  • dcf_ log_ path = ‘/dcf_ perf_ 03/px01/cluster/gaussdb_ log/px01/dcf_ log’
  • dcf_ config =
    ‘[“stream_ id”:1,”node_ id”:1,”ip”:”8.92.1.85”,”port”:16683,”role”:”LEADER”),(“stream_ id”:1,”node_ id”:2,”ipp”:”8.92.1 .86”,”port”:16683,”role”:”FOLLOWER”),”stream_ id”:1,”node_ id”:3,”ip”:”8.92.1.87”,”port”:16683,”role”:”FOLLOWER”]]
  • dcf_ Ssl = off
  • dcf_ mec_ batch_ size=0

Author

Lamber

Posted on

2022-04-18

Updated on

2022-04-25

Licensed under