DM8 单机双节点 DSC 集群部署与故障验证:共享存储、CSS、ASM 与节点接管
DM8 单机双节点 DSC 集群部署与故障验证:共享存储、CSS、ASM 与节点接管
一、DSC 与普通主备的本质差异
普通主备架构中,每个实例有自己的一套数据库文件,主库通过日志传输保持备库数据一致。
DSC 的两个数据库实例则共享数据文件:
这意味着:
DSC0 写入的数据不需要“复制”给 DSC1;DSC1 能立即读到相同数据,是因为两个节点访问同一套数据库文件;节点故障时,存活节点继续访问共享存储;集群成员关系、投票和资源协调必须先于数据库实例工作。
因此,DSC 部署不能只关注dm.ini。底层 DCR、VOTE、CSS 和 ASM 任一环节不正确,数据库层都无法形成正常集群。
二、实验环境
本次记录中的环境如下:
| 项目 | 配置 |
|---|---|
| 操作系统 | 银河麒麟 V10 SP1 x86_64 |
| 数据库版本 | DM8 Enterprise 8.1.5.60 |
| DM 安装目录 | /home/dmdba/dmdbms |
| 服务器地址 | 192.168.200.253 |
| DSC0 数据库端口 | 8236 |
| DSC1 数据库端口 | 8237 |
| MAL 端口 | 8336 / 8337 |
| ASM 端口 | 8436 / 8437 |
| CSS 端口 | 8636 / 8637 |
共享设备规划如下:
| 用途 | 设备 |
|---|---|
| DCR | /dev/dm/asm-dmdcr |
| VOTE | /dev/dm/asm-dmvote |
| 数据磁盘 | /dev/dm/asm-dmdata |
| 归档磁盘 | /dev/dm/asm-dmarch |
虽然是单机部署,两个逻辑节点仍应使用不同实例名、端口、配置目录和运行目录。这样才能模拟节点独立启动、停止和恢复的过程。
三、部署前检查
1. 用户与设备权限
数据库、CSS 和 ASM 进程通常由dmdba用户运行。首先确认裸设备存在:
ls-l/dev/dm/asm-dmdcrls-l/dev/dm/asm-dmvotels-l/dev/dm/asm-dmdatals-l/dev/dm/asm-dmarch需要重点检查:
- 设备属主、属组是否允许
dmdba读写; - 设备映射在重启后是否仍然存在;
- DCR、VOTE、DATA、ARCH 是否误指向同一块设备;
- 设备是否已经被其他实验环境占用;
- udev 规则是否保证设备名稳定。
裸设备权限错误时,ASM 可能直接启动失败;设备名变化时,则会出现“配置正确但找不到磁盘”的现象。
2. 端口冲突
单机双节点所有监听地址都落在同一台主机上,端口冲突比多机部署更常见:
ss-lntp|grep-E"8236|8237|8336|8337|8436|8437|8636|8637"如果旧的 DSC、主备或 DMDPC 进程没有停止,即使数据库端口不冲突,也可能占用 MAL、ASM 或 CSS 端口。
3. 资源边界
单机部署时应先停止无关数据库实例。尤其不要在压测期间同时运行:
DSC0 + DSC1 + DW01 + GRP3_RT_01 + GRP3_RT_02 + GRP3_LOCAL_01这些实例会共同竞争 CPU、内存和磁盘,导致性能曲线的变化无法归因。
四、为什么 DCR 和 VOTE 必须最先完成
DCR 保存集群控制信息,VOTE 用于成员投票和脑裂防护。二者是 CSS 判断节点身份和集群状态的基础。
部署顺序应当遵循:
操作系统与裸设备 ↓ DCR / VOTE 初始化 ↓ CSS0 / CSS1 ↓ ASM0 / ASM1 ↓ DMDATA / DMARCH 磁盘组 ↓ DSC 数据库初始化 ↓ DSC0 / DSC1最常见的错误是跳过底层检查,直接启动 DMSERVER。此时日志只会显示无法连接 ASM、无法读取集群控制信息或节点未加入集群,而问题根源实际上在 DCR、VOTE 或 CSS。
五、CSS 与 ASM 的配置要点
1. CSS
CSS 负责集群成员管理、资源协调和节点状态判断。双节点配置必须保证:
- 节点编号唯一;
- CSS 实例名唯一;
- CSS 通信端口不冲突;
- 两个节点引用相同的 DCR 和 VOTE;
- OGUID 与所属 DSC 集群一致。
启动后应先通过 CSS 监视工具确认两个逻辑节点均已加入,再继续启动 ASM。
2. ASM
ASM 向数据库实例提供共享存储。ASM0 和 ASM1 需要访问相同的数据与归档裸设备,但各自具有独立的实例名和通信端口。
创建磁盘组时应将:
/dev/dm/asm-dmdata → DMDATA /dev/dm/asm-dmarch → DMARCH数据库初始化目录、数据文件和归档目标应引用 ASM 磁盘组,而不是某个节点自己的普通文件系统目录。否则即使两个实例都能启动,也不是真正的共享存储 DSC。
六、初始化 DSC 数据库
在 CSS 和 ASM 均正常后,初始化 DSC 数据库。两个节点的dm.ini要保证以下关系:
# DSC0 INSTANCE_NAME = DSC0 PORT_NUM = 8236 # DSC1 INSTANCE_NAME = DSC1 PORT_NUM = 8237此外还要分别配置 MAL 通信:
DSC0 MAL:8336 DSC1 MAL:8337数据库级配置的关键不是单个参数,而是整体一致性:
- 两个节点必须属于同一数据库;
- 数据文件、控制文件和日志规划一致;
- 节点号、实例名和端口唯一;
- ASM 连接信息正确;
- DCR 中登记的节点与实际配置一致。
七、启动顺序与状态确认
推荐启动顺序如下:
# 1. 启动 CSS0、CSS1# 2. 启动 ASM0、ASM1# 3. 检查 DMDATA、DMARCH 磁盘组# 4. 启动 DSC0、DSC1# 5. 启动 dmcssm 观察集群关闭时采用相反顺序:
DMSERVER → ASM → CSS最终实验状态为:
DSC0 Control Node OPEN DSC1 Normal Node OPEN n_ok_ep = 2这里的n_ok_ep=2表示两个数据库端点均处于可用状态。只看到两个dmserver进程并不能证明集群正常,必须结合dmcssm中的节点角色、工作状态和有效端点数判断。
八、共享数据验证
在 DSC0 建表并写入:
CREATETABLEDSC_TEST(IDINT,WRITE_NODEVARCHAR(20),CREATE_TIMEDATETIME);INSERTINTODSC_TESTVALUES(1,'DSC0',SYSDATE);COMMIT;随后连接 DSC1:
SELECT*FROMDSC_TESTORDERBYID;如果 DSC1 能立即查询到 DSC0 写入的数据,可以证明两个节点访问同一数据库。但为了把证据链做完整,还应记录:
SELECTINSTANCE_NAME,STATUS$,MODE$FROMV$INSTANCE;这样截图中可以同时看到“当前连接的是 DSC1”和“查询到了 DSC0 写入的数据”,避免把同一个端口的重复查询误认为跨节点验证。
九、单节点故障验证
实验中停止 DSC1 后,dmcssm显示:
DSC0 OPEN WORKING OK TRUE DSC1 OPEN WORKING ERROR FALSE n_ok_ep = 1此时在 DSC0 上仍然可以执行查询和写入。测试表已有1552行,并在故障期间继续插入:
INSERTINTODSC_TESTVALUES(1553,'DSC1_DOWN_WRITE',SYSDATE);COMMIT;这项验证证明:
- 单节点故障没有使共享数据库整体不可用;
- 存活节点仍可处理写事务;
- 故障节点恢复后应重新加入相同集群,而不是重新初始化数据库;
- 高可用依赖服务名和客户端重连,不能只测试存活节点固定端口。
十、压力下的 DSC 故障
故障测试使用 10 线程、60 秒升压和 720 秒持续时间。三轮单节点故障结果如下:
| 场景 | 总请求 | 失败 | 错误率 | 稳态 TPS | CV |
|---|---|---|---|---|---|
| 普通节点下线(首轮) | 489,303 | 10 | 0.0020% | 701.164 | 14.229% |
| 普通节点下线(复测) | 463,731 | 10 | 0.0022% | 661.980 | 17.160% |
| 控制节点下线 | 481,198 | 10 | 0.0021% | 687.373 | 14.797% |
错误类型主要是 JDBC 连接重置和网络通信异常。这说明已经建立在故障节点上的连接会失败,但业务通过重连或节点重选后可以恢复。
图 1 DSC 控制节点下线场景的 JMeter HTML 原始页面截图。
以控制节点下线为例:
21:52:14 开始下线 21:53:37 停机操作完成 第 200 秒窗口出现 10 个失败 第 210、220 秒窗口无完成请求 第 230 秒窗口恢复成功吞吐由 10 秒窗口只能得出“业务约 30 秒级恢复”,合理观察区间约为 20~40 秒。停机命令执行了 83 秒,但这不是业务 RTO,因为存活节点在停机命令结束前已经开始恢复服务。
十一、摸高结果:80 线程成功不等于 80 线程才到极限
DSC 摸高覆盖 5~80 线程,所有有效轮次均为零错误:
| 线程数 | 稳态 TPS | CV | 平均响应 |
|---|---|---|---|
| 5 | 773.067 | 8.315% | — |
| 10 | 668.120~711.700 | 4.550%~7.795% | 0.976 ms |
| 20 | 659.950 | 6.023% | 1.028 ms |
| 30 | 593.310 | 7.351% | 1.012 ms |
| 40 | 576.820 | 4.810% | 0.958 ms |
| 50 | 580.670 | 10.332% | 1.123 ms |
| 60 | 619.310 | 7.634% | 1.169 ms |
| 80 | 603.910 | 4.514% | 1.253 ms |
图 2 DSC 80 线程摸高轮次的 JMeter Dashboard 原始截图。
图 3 DSC 80 线程摸高轮次的 JMeter HTML 吞吐页面。
结论:
- 本次最高验证到 80 线程,且零错误;
- 5~20 线程已经接近本环境的吞吐平台;
- 30~80 线程主要落在约 577~619 TPS;
- 增加线程没有带来线性吞吐增长;
- 80 线程表示“仍能承载”,不表示“到 80 线程才达到性能上限”。
十二、从双节点 DSC 扩展到 DSC 加实时备库
实验后续还形成了DSC0 + DSC1 + DW01架构:
| 实例 | 数据库端口 | MAL | Watcher | 实例守护 |
|---|---|---|---|---|
| DSC0 | 8236 | 8336 | 8736 | 8836 |
| DSC1 | 8237 | 8337 | 8737 | 8837 |
| DW01 | 8238 | 8338 | 8738 | 8838 |
守护组为GDSCDW1,数据守护 OGUID 为826072,DSC CSS OGUID 为826071。这两个 OGUID 用途不同,不能混用。
创建 DW01 时不能单独初始化一个新库,而应:
- 使用 DMRMAN 对 DSC 数据库进行备份;
- 在 DW01 还原数据;
- 执行恢复;
- 更新 DB_MAGIC;
- 配置与 DSC 一致的初始化参数;
- 配置实时归档、MAL 和 Watcher;
- 将 DW01 设置为 STANDBY。
这一架构同时获得了:
- DSC 节点级高可用;
- 共享存储数据库之外的独立实时副本;
- DSC 整体故障或共享存储故障时的灾备接管基础。
十三、部署中最容易卡住的地方
1. 启动顺序错误
数据库依赖 ASM,ASM 依赖 CSS,CSS 依赖 DCR/VOTE。应从底层向上启动,从上层向下关闭。
2. 裸设备权限或映射变化
普通目录权限正确并不能代表裸设备可读写。重启后设备名变化也会使原配置失效。
3. 把跨节点查询当作复制验证
DSC 使用共享数据文件,DSC1 读到 DSC0 的数据并不是日志复制。博客和报告中应使用“共享数据可见性”,不要使用“主备同步成功”描述。
4. 固定端口掩盖客户端高可用问题
直接连接 DSC0 或 DSC1,只能验证该节点。业务必须通过 DSC 服务名访问,才能验证节点重选和重连。
十四、结论
本次实验完成了双节点 DSC 从裸设备、DCR/VOTE、CSS、ASM、数据库初始化到节点启动的完整链路。DSC0 和 DSC1 均处于 OPEN 状态,n_ok_ep=2;通过跨节点写入与查询验证了共享数据可见性。
持续压力下停止普通节点或控制节点,整体错误率约为0.002%,存活节点继续提供服务。现有 10 秒窗口支持“业务约 30 秒级恢复”的判断,但不足以给出秒级精确 RTO。摸高测试已验证至 80 线程零错误,但吞吐在低并发已进入平台区,因此不能将 80 线程直接解释为生产容量上限。