ITPub博客

首页 > 数据库 > 国内数据库 > 达梦DM9自治容灾集群DMAFC安装与测试

达梦DM9自治容灾集群DMAFC安装与测试

原创 国内数据库 作者:chenoracle 时间:2026-09-18 16:22:39 0 删除 编辑

自治容灾集群是什么?

自治容灾集群(DM Autonomous Failover Cluster),简称DMAFC。
DMAFC是一套基于Raft一致性协议构建的高可用数据库解决方案,专门为满足两地三中心、高并发、高可靠等业务场景而设计。
主打自动化的主库选举、故障检测与恢复机制,消除单点故障风险,确保数据零丢失与业务连续性。无论是金融交易系统、实时数据分析平台,还是需要强一致性保障的物联网应用,它都能提供7x24小时不间断稳定服务。
简单来说,DMAFC把分布式数据库里那套成熟的“自动选举”机制,搬到了集中式数据库的容灾里。

上述描述的参考链接:

https://mp.weixin.qq.com/s/LbRWv_nvsnnVBoJG0U8krg

DMAFC部署

操作系统需求

图片.png

环境说明

图片.png

操作系统:
图片.png

初始化实例

3个节点,分别安装DM9,注意实例名不同
跳过创建用户、目录 …等操作,和DM8没什么区别。
本次采用图形化安装,主要想看看DM9的图形界面有哪些优化:
图片.png
图片.png
图片.png
图片.png
图片.png
图片.png
图片.png
图片.png
图片.png

脱机备份和恢复

图形化安装完DM9以后,自动启动达梦实例和DMAP服务,脱机备份前需要先关闭实例,3个节点,依次执行:

shutdown immediate;

节点1:脱机备份

dmrman CTLSTMT="BACKUP DATABASE '/dm9/data/CJC/dm.ini' FULL TO BACKUP_FILE1 BACKUPSET '/dm9/bak/tmp/BACKUP_FILE_01'"

图片.png

备份文件通过scp工具上传到节点2、节点3:

节点2,节点3:执行恢复

dmrman CTLSTMT="restore database '/dm9/data/CJC/dm.ini' from backupset '/dm9/bak/tmp/BACKUP_FILE_01'"
dmrman CTLSTMT="recover database '/dm9/data/CJC/dm.ini' from backupset '/dm9/bak/tmp/BACKUP_FILE_01'"
dmrman CTLSTMT="recover database '/dm9/data/CJC/dm.ini' update DB_MAGIC "

图片.png

DMAFC配置

修改dm.ini 配置文件

3个节点分别修改dm.ini配置文件:

[dmdba@cjc-db-19 ~]$ vi /dm9/data/CJC/dm.ini
ARCH_INI = 1
ALTER_MODE_STATUS = 0

新建dmarch.ini配置文件

节点1:

[root@cjc-db-19 ~]# cat /dm9/data/CJC/dmarch.ini
XMAL_HB_INTERVAL = 5
RAFT_HB_INTERVAL = 150
RAFT_VOTE_INTERVAL = 3000
XMAL_IP = 192.168.244.159
XMAL_PORT = 61101
RAFT_SELF_ID = 1
[ARCHIVE_RAFT1]
ARCH_TYPE = RAFT
ARCH_DEST = CJC01
ARCH_DEST_IP = 192.168.244.158
ARCH_DEST_PORT = 61101
ARCH_DEST_ID = 2
[ARCHIVE_RAFT2]
ARCH_TYPE = RAFT
ARCH_DEST = CJC02
ARCH_DEST_IP = 192.168.244.170
ARCH_DEST_PORT = 61101
ARCH_DEST_ID = 3
[ARCHIVE_LOCAL]
ARCH_TYPE = LOCAL
ARCH_DEST = /dm9/arch
ARCH_FILE_SIZE = 64
ARCH_SPACE_LIMIT = 0

图片.png

节点2:

[root@cjc-db-18 ~]# cat /dm9/data/CJC/dmarch.ini
XMAL_HB_INTERVAL = 5
RAFT_HB_INTERVAL = 150
RAFT_VOTE_INTERVAL = 4000
XMAL_IP = 192.168.244.158
XMAL_PORT = 61101
RAFT_SELF_ID = 2
[ARCHIVE_RAFT1]
ARCH_TYPE = RAFT
ARCH_DEST = CJC
ARCH_DEST_IP = 192.168.244.159
ARCH_DEST_PORT = 61101
ARCH_DEST_ID = 1
[ARCHIVE_RAFT2]
ARCH_TYPE = RAFT
ARCH_DEST = CJC02
ARCH_DEST_IP = 192.168.244.170
ARCH_DEST_PORT = 61101
ARCH_DEST_ID = 3
[ARCHIVE_LOCAL]
ARCH_TYPE = LOCAL
ARCH_DEST = /dm9/arch
ARCH_FILE_SIZE = 64
ARCH_SPACE_LIMIT = 0

图片.png

节点3:

[root@cjc-db-20 ~]# cat /dm9/data/CJC/dmarch.ini
XMAL_HB_INTERVAL = 5
RAFT_HB_INTERVAL = 150
RAFT_VOTE_INTERVAL = 5000
XMAL_IP = 192.168.244.170
XMAL_PORT = 61101
RAFT_SELF_ID = 3
[ARCHIVE_RAFT1]
ARCH_TYPE = RAFT
ARCH_DEST = CJC
ARCH_DEST_IP = 192.168.244.159
ARCH_DEST_PORT = 61101
ARCH_DEST_ID = 1
[ARCHIVE_RAFT2]
ARCH_TYPE = RAFT
ARCH_DEST = CJC01
ARCH_DEST_IP = 192.168.244.158
ARCH_DEST_PORT = 61101
ARCH_DEST_ID = 2
[ARCHIVE_LOCAL]
ARCH_TYPE = LOCAL
ARCH_DEST = /dm9/arch
ARCH_FILE_SIZE = 64
ARCH_SPACE_LIMIT = 0

图片.png

DMAFC测试

启动集群

3个节点分别启动数据库,启动到mount:

[dmdba@cjc-db-19 ~]$ dmserver /dm9/data/CJC/dm.ini mount
[dmdba@cjc-db-18 ~]$ dmserver /dm9/data/CJC/dm.ini mount
[dmdba@cjc-db-20 ~]$ dmserver /dm9/data/CJC/dm.ini mount

检查集群

节点1是 PRIMARY ,节点2、节点3 是STANDBY 。

SQL> SELECT INSTANCE_NAME, RAFT_STAT, SYS_MODE, SYS_STATUS FROM V$GLOBAL_RAFT_INFO;
行号       INSTANCE_NAME RAFT_STAT SYS_MODE SYS_STATUS
---------- ------------- --------- -------- ----------
1          CJC           LEADER    PRIMARY  OPEN
2          CJC01         FOLLOWER  STANDBY  OPEN
3          CJC02         FOLLOWER  STANDBY  OPEN
已用时间: 4.795(毫秒). 执行号:601.

图片.png

select * from V$RAFT_SWITCH_INFO;

图片.png

select * from V$GLOBAL_RAFT_INSTANCE;

图片.png

图片.png

数据同步测试

节点1:新增数据

SQL> create table cjc.t3(id int);
操作已执行
已用时间: 13.848(毫秒). 执行号:905.
SQL>
SQL> insert into cjc.t3 values(1);
影响行数 1
已用时间: 2.032(毫秒). 执行号:906.
SQL> commit;
操作已执行
已用时间: 3.774(毫秒). 执行号:907.

节点2、节点3:只读库,数据正常同步

SQL> create table t1(id int);
create table t1(id int);
[-710]:试图在STANDBY模式下,修改用户库.
已用时间: 1.487(毫秒). 执行号:0.
SQL> select * from cjc.t3;
行号       id
---------- -----------
1          1
已用时间: 2.076(毫秒). 执行号:1.

主备切换测试

关闭主库

shutdown immediate

图片.png

节点2:自动变成主库

SQL> SELECT INSTANCE_NAME, RAFT_STAT, SYS_MODE, SYS_STATUS FROM V$GLOBAL_RAFT_INFO;
行号       INSTANCE_NAME RAFT_STAT SYS_MODE SYS_STATUS
---------- ------------- --------- -------- ----------
1          CJC01         LEADER    PRIMARY  OPEN
2          CJC02         FOLLOWER  STANDBY  OPEN
已用时间: 4.585(毫秒). 执行号:801.

图片.png

新主库,插入数据
图片.png

启动节点1数据库,变成STANDBY自动加入集群,数据自动同步
图片.png

关闭所有STANDBY节点,主无法写入数据
图片.png

Ctrl+c 后,再次执行
图片.png

对应切换日志如下:

2026-08-24 20:17:35.753 [INFO] database P0000027760 T0000000000000027893  rraft_elect_schedule_thread follower elect_start!
2026-08-24 20:17:35.753 [INFO] database P0000027760 T0000000000000027893  [rraft] l_term_id: 6 -> 7.
2026-08-24 20:17:35.754 [INFO] database P0000027760 T0000000000000027893  [rraft] raft_stat: FOLLOWER -> CANDIDATE.
2026-08-24 20:17:35.754 [INFO] database P0000027760 T0000000000000027893  rraft election-start[self elect timeout] term[6->7] state[FOLLOWER->CANDIDATE] leader[CJC->UNKNOWN].
2026-08-24 20:17:38.757 [INFO] database P0000027760 T0000000000000029607  [rraft] l_term_id: 7 -> 8.
2026-08-24 20:17:38.757 [INFO] database P0000027760 T0000000000000029607  [rraft] raft_stat: CANDIDATE -> FOLLOWER.
2026-08-24 20:17:38.757 [INFO] database P0000027760 T0000000000000029607  [rraft] [vote] received g_seq is larger, received[log_term:6, g_seq:3397, c_seq:3396], self[log_term:6, g_seq:3397, c_seq:3396]
2026-08-24 20:17:38.757 [INFO] database P0000027760 T0000000000000029607  rraft recv vote request from[CJC01], state-changed[new term elect req] term[7->8] state[CANDIDATE->FOLLOWER] leader[UNKNOWN], vote_granted[1].
2026-08-24 20:17:38.757 [INFO] database P0000027760 T0000000000000029607  [rraft] [send] node[id: 2] vote res, term: 8, voted: 1.
2026-08-24 20:17:38.759 [INFO] database P0000027760 T0000000000000029607  rraft recv hb from[CJC01], election-end[leader elected] term[8] state[FOLLOWER] leader[UNKNOWN->CJC01].
2026-08-24 20:17:38.838 [INFO] database P0000027760 T0000000000000027832  rafil_close_with_trunc file[/dm9/arch/STANDBY_ARCHIVE_0x4F294787_EP0_0xEE2F95F_2026-08-24_17-05-27.log] to 262144 len, g_next_seq:3397, ret = 1!
2026-08-24 20:17:38.838 [INFO] database P0000027760 T0000000000000027832  rfil_close_low set arch rfil[/dm9/arch/STANDBY_ARCHIVE_0x4F294787_EP0_0xEE2F95F_2026-08-24_17-05-27.log]'s sta to inactive, l_next_seq = 3397, g_next_seq = 3397, clsn = 53697, handle = 47, free=262144, len=262144
2026-08-24 20:17:38.838 [INFO] database P0000027760 T0000000000000027832  rafil_file_create [/dm9/arch/STANDBY_ARCHIVE_0x390358F9_EP0_0xEE2F95F_2026-08-24_17-17-38.log] start
2026-08-24 20:17:38.839 [INFO] database P0000027760 T0000000000000027832  rfil_close_low set arch rfil[/dm9/arch/STANDBY_ARCHIVE_0x390358F9_EP0_0xEE2F95F_2026-08-24_17-17-38.log]'s sta to inactive, l_next_seq = 2457, g_next_seq = 2457, clsn = 0, handle = 47, free=4096, len=67108864
2026-08-24 20:17:38.840 [INFO] database P0000027760 T0000000000000027832  rafil_file_create [/dm9/arch/STANDBY_ARCHIVE_0x390358F9_EP0_0xEE2F95F_2026-08-24_17-17-38.log] success, handle = 47
2026-08-24 20:17:38.840 [INFO] database P0000027760 T0000000000000027832  rafil_switch_if_necessary, rafil_new_arch_file, rafil create new arch file [/dm9/arch/STANDBY_ARCHIVE_0x390358F9_EP0_0xEE2F95F_2026-08-24_17-17-38.log] success
2026-08-24 20:17:38.840 [INFO] database P0000027760 T0000000000000027847  rlog4_apply_db_magic_set, set apply_info_lsn[53397->53697]
2026-08-24 20:17:38.840 [INFO] database P0000027760 T0000000000000027847  rlog4_apply_db_magic_set, set p_db_magic[1328105351->956520697], n_apply_ep[1->1]
2026-08-24 20:17:38.856 [INFO] database P0000027760 T0000000000000029607  rraft_process_ini_sync_primary success, set msg_ini_version to 671323118
2026-08-24 20:18:07.044 [INFO] database P0000027760 T0000000000000027789  rraft_set_arch_chg_info, set rraft_sys.arch_chg_flag TRUE, arch_chg_stat 0 to 9.
2026-08-24 20:18:07.046 [INFO] database P0000027760 T0000000000000027789  rraft_reset_arch_chg_info success.

切换期间,通过查看节点3的日志,可以看到,切换过程大概如下:
1.选举触发
本节点原为 Follower,Leader 是 CJC。
20:17:35 发生选举超时(elect timeout),说明在规定时间内未收到原 Leader 的心跳,判断 Leader 可能故障或网络隔离。
节点提升任期(term 6→7),状态转为 Candidate,发起选举。

2.快速退让并投票
仅 3 秒后,节点收到来自 CJC01 的投票请求,且对方任期更高(term=8)。
Raft 协议要求 Candidate 若收到更高任期的投票请求,必须立即退让,转为 Follower 并投票。
本节点正确执行了该逻辑:状态 CANDIDATE→FOLLOWER,vote_granted=1。

3.新 Leader 确认
随后收到 CJC01 的心跳,确认 CJC01 当选为新 Leader。
本节点 Leader 从 UNKNOWN 变为 CJC01,选举结束,集群恢复有主状态。

4.数据同步与归档切换
节点开始接收新 Leader 的日志:
关闭旧归档文件并截断至安全长度(262144 字节)。
创建新归档文件 STANDBY_ARCHIVE_…_17-17-38.log。
apply_info_lsn 前进(53397→53697),说明日志已应用到新位置。
db_magic 值变化,表示数据库内部状态/角色信息已更新。
这些操作表明本节点作为 Follower 正在追赶新主的数据,确保数据一致性。

5.初始同步完成
rraft_process_ini_sync_primary success 表明备库已完成与新主库的初始同步,可以正常提供只读服务或继续作为备库运行。

6.归档变更处理
20:18:07 设置 arch_chg_flag,随后重置成功。
这通常用于切换后更新归档配置、清理旧归档信息,确保后续日志归档正确。

总结

1.仅供参考
达梦官方技术文档里没有找到DMAFC自治容灾集群的相关内容,部署部分参考了鲲鹏昇腾开发者社区-三节点AFC集群搭建操作指南,全文仅供参考,如有疑问,请咨询达梦原厂工程师;

2.和达梦数据守护集群DMDataWatch的区别
DMAFC的安装配置比DMDataWatch简单很多,没有守护进程(dmwatcher)、监视器(dmmonitor)、MAL组件等,为容灾、高可用场景新增了一种不错的解决方案。
DMDataWatch:
图片.png

DMAFC:
图片.png

参考

《DM9,打出一张容灾王 牌》
https://mp.weixin.qq.com/s/LbRWv_nvsnnVBoJG0U8krg
《三节点AFC集群搭建操作指南》
https://hwcomputing.csdn.net/6a7ae96010ee7a33f2996f13.html
《DM8 数据守护与读写分离集群》
https://eco.dameng.com/document/dm/zh-cn/pm/data-watch-overview.html

#达梦数据库 #达梦同行者征文

欢迎关注我的公众号《 IT小Chen》


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29785807/viewspace-3182997/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
Oracle ACE、OCMU 用户组成员、Oracle 11g OCM、微信公众号"IT小Chen"

注册时间:2014-08-05

  • 博文量
    853
  • 访问量
    2722093