常见的高可用存储架构有主备、主从、主主、集群、分区,每一种又可以根据业务的需求进行一些特殊的定制化功能,由此衍生出更多的变种。本文主要介绍的达梦数据守护集群是一种基于主备的双机切换集群。
常用的主备复制和主从复制存在两个共性的问题:
- 主机故障后,无法进行写操作。
- 如果主机无法恢复,需要人工指定新的主机角色。
双机切换就是为了解决这两个问题而产生的,包括主备切换和主从切换两种方案。简单来说,这两个方案就是在原有方案的基础上增加“切换”功能,即系统自动决定主机角色,并完成角色切换。
要实现一个完善的切换方案,必须考虑这几个关键的设计点:
- 如何进行切换?
- 切换决策是什么?主要包括几方面:切换时机、切换策略、自动程度。
- 如何解决数据冲突?
由于主备切换和主从切换在切换的设计上没有差别,这里主备切换为例,一起来看看达梦的双机切换架构是如何设计的。
主备间是如何进行状态切换的?
要进行状态切换,必然要先确定状态是否异常。那么集群是如何检测数据库状态的?
- 状态切换的渠道:是相互间互相连接,还是第三方仲裁?这里应该是第三方仲裁。
- 状态检测的内容:例如机器是否掉电、进程是否存在、响应是否缓慢等。
状态检测
守护进程
在DM数据守护架构中,在数据库实例所在机器上还有一个单独的进程,我们把它叫作守护进程(dmwatcher)。数据守护进程主要功能有监控数据库实例、发送状态信息、监控其他守护进程、接受监视器消息、主备库启动运行、备库故障处理、备库异常处理、主库故障处理、故障回复处理。和状态检测相关的功能主要有监控数据库实例、发送状态信息、监控其他守护进程。

监视器
DM的仲裁功能通过监视器来实现。监视器是DM数据守护系统的重要组成部分。监视器的基本作用有:监控数据守护系统、管理数据守护系统、确认状态信息、发起故障自动接管命令。涉及到状态检测,这里我们只分析监控功能和确认状态信息功能。
- 监控数据守护系统
- 接收守护进程发送的消息,显示主、备数据库状态的变化,以及故障切换过程中,数据库模式、状态变化的完整过程。
- 确认状态信息
- 用于故障自动切换的数据守护系统中,主、备库进行故障处理之前,需要通过监视器进行信息确认,确保对应的备库或者主库真的产生异常了,避免主备库之间网络故障引发脑裂。
主备切换
当主库出现故障时,自动切换模式下,确认监视器会自动选择符合条件的备库进行接管。 手动切换模式下,可以先在监视器上执行 Choose Takeover 命令,选出守护进程组中可以接管的备库。
为了避免备库接管后,造成守护进程组分裂,执行 Takeover 必须满足下列条件:
- 主库是 Primary 模式、Open 状态时,发生故障
- 主库守护进程故障,故障前是 Startup/Open/Recovery 状态;或者主库守护进程正常 。
- 主库故障前到接管备库的归档状态为 Valid,保证所以已提交事务都已同步到备库。
- 接管备库是 Standby 模式、Open 状态
- 接管备库的守护进程控制文件状态为 Valid(内存值)
- 故障主库和接管备库的 Open 记录项内容相同
假设主库 A 故障时,在故障自动切换模式下确认监视器自动选出待接管备库 B 并通知 备库 B 自动接管,或者在故障手动切换模式下,通过监视器上的 Choose Takeover 命令, 选出待接管备库 B,在监视器上输入 Takeover 命令通知备库 B 执行接管,这两种方式的 接管执行流程是一样的。
以备库 B 为例,接管的执行流程包括:
- 监视器通知守护进程(B)切换为 Takeover 状态
- 实时主备环境下,通知备库(B) APPLY KEEP_PKG
- 通知备库(B) Mount
- 通知(B) 切换为 Primary 模式
- 通知(B) 修改到所有归档目标的归档状态为 Invalid
- 通知新的主库(B) Open
- 通知守护进程(B)切换为 Open 状态
- 修改守护进程 (B)的INST_RECOVER_TIME内存值为3秒(默认60秒),确保尽快启动B->C 的故障恢复流程,同步主库数据完成后,重新将 B->C 的归档设置为 Valid 状态。
主备间的切换决策是什么?
主要包括几方面:切换时机、切换策略、自动程度。
- 切换时机:什么情况下备机应该升级为主机?是机器掉电后备机才升级,还是主机上的进程不存在就升级,还是主机响应时间超过2s就升级,还是3分钟内主机连续重启3次就升级等。
- 1.主库数据库实例异常终止,主库守护进程正常。 采用超时机制。DW_ERROR_TIME
- 2.主库硬件故障、或者数据库实例和守护进程同时故障。
- 3.主库网络故障,主备库之间、主库与监视器之间连接异常。
- 切换策略:原来的主机故障恢复后,要再次切换,确保原来的主机继续做主机,还是原来的主机故障恢复后自动成为新的备机?
- 本地库和远程库相等。如果其中一个库是 Primary&Open 或者 Primary&Suspend 状态,则直接将其认定 为主库,另一个库认定为备库。 否则需要进一步比较两个库的 APPLY 信息,比较结果可能会选出有效的主库和备库, 也可能出现分裂,需要用户干预。在确认监视器模式下,已做主备切换,后加入的库为备库。
- 远程库包含在本地库中。 使用本地库包含关系之后的第一条 Open 记录项中的 APPLY 信息和远程库的 APPLY 信 息比较大小,远程库小于或等于的情况下,远程库的守护进程再继续根据模式、状态信息确 定下一步动作,最终可以将其作为备库重加入守护系统。
- 本地库包含在远程库中 使用远程库包含关系之后的第一条 Open 记录项中的 APPLY 信息和本地库的 APPLY 信 息比较大小,本地库小于或等于的情况下,本地库的守护进程再继续根据模式、状态信息确 定下一步动作,最终可以将其作为备库重加入守护系统。
- 本地库和远程库不相等,也没有包含关系 如果其中一个库处于 Primary&Open 状态,另一个库是备库,或者是 Mount 状态的 主库,则另一个库的守护进程会将自己设置为 Split 分裂状态,创建 dmwatcher.ctl 文 件,并通知本地库强制关闭。如果守护进程无法选出有效主库,则切换为 Startup 状态, 并等待用户干预。
- 自动程度:切换是完全自动的,还是半自动的?例如,系统判断当前需要切换,但是需要人工做最终的确认操作(例如,单机一些“切换”按钮)。
- 在确认监视器下自动切换。在非确认监视器下需要手动切换。
主备间是如何解决数据冲突的?
当原有故障的主机恢复后,新旧主机之间可能存在数据冲突。例如,用户在旧主机上新增了一条ID为100的数据,这个数据还没有复制到旧的备机,此时发生了切换,旧的备机升级为新的主机,用户又在新的主机上新增了一条ID为100的数据,当旧的故障主机恢复后,这两条ID都为100的数据,应该怎么处理?
实时主备系统中,主库提供完整的数据库 功能,备库提供只读服务。主库修改数据产生的Redo日志,通过实时归档机制,在写入联机Redo日志文件之前发送到备库,实时备库通过重演Redo日志与主库保持数据同步。当主库出现故障时,未提交的事务会回滚,备库在将所有Redo日志重演结束后,就可以切换为主库对外提供数据库服务。由此可见,不存在数据冲突的情况。
参考资料:
《DM8 - Data Watch And Read Write Shunt V4.0》