在达梦数据库的集群方案中,DSC(数据共享集群)是实现高可用和读写分离的核心技术之一。本文将从零开始,手把手带你在一台虚拟机上搭建一套2节点的DSC集群。
DSC全称达梦数据共享集群,是达梦数据库中用于实现高可用和负载均衡的一种集群架构。
它的核心思想是:多个数据库实例同时挂载同一份数据文件,协同对外提供服务。
你可以这样理解:
DSC集群主要包含三个核心组件:
| 组件 | 全称 | 作用 |
|---|---|---|
| DMCSS | 集群控制服务 | 负责监控各个节点状态,检测故障,防止脑裂 |
| DMASM | 自动存储管理 | 负责管理共享磁盘,将裸盘组织成磁盘组供数据库使用 |
| DMSERVER | 数据库实例 | 负责处理SQL请求,对外提供服务 |
“两节点”是指DSC集群由两个数据库实例组成,分别称为 DSC0 和 DSC1。
在我们的实验环境中,这两个节点部署在同一台虚拟机上,通过不同的端口号进行区分:
| 节点 | 服务端口 | MAL通信端口 | 角色 |
|---|---|---|---|
| DSC0 | 2221 | 22261 | 实例0 |
| DSC1 | 2223 | 22262 | 实例1 |
两个节点共享同一份数据(存储在ASM磁盘组中),任何一台节点出现故障,另一台可以立即接管服务。
在生产环境中,这两个节点通常会部署在不同的物理服务器上,以实现真正的主机级高可用。
在搭建达梦DSC集群前,使用 df -h 和 lsblk 两个命令查看磁盘,发现:
df -h 只能看到系统盘 /dev/vda3(已挂载到根目录 /)
lsblk 可以看到四块额外的磁盘:vdb、vdc、vdd、vde,但它们没有挂载点
这四块磁盘(vdb~vde)目前是裸盘状态:
这正是DSC所需要的状态!因为达梦的ASM(自动存储管理)会直接接管这些裸盘,在上面创建磁盘组存储数据,而不需要通过操作系统文件系统。
| 磁盘 | 大小 | 规划用途 | DSC中的角色 |
|---|---|---|---|
/dev/vdb |
500M | DCR磁盘 | 存储集群配置信息(相当于集群的"户口本") |
/dev/vdc |
500M | Vote磁盘 | 心跳检测、防止脑裂(节点故障时投票选举主节点,防止集群脑裂) |
/dev/vdd |
20G | 数据磁盘组 | 存放数据库数据文件 |
/dev/vde |
50G | 日志磁盘组 | 存放数据库日志文件 |
在4块共享磁盘中:2块较小的磁盘(500M)用于创建DCR、VOTE 磁盘;2块较大的 磁盘(20G、50G)用于创建ASM磁盘组(数据磁盘组DMDATA和联机日志磁盘组DMLOG)。
在达梦《DM8共享存储集群》手册中,官方提供了两种磁盘绑定方式(使用multipath软件和UDEV方式),两种方式实现效果完全相同,但UDEV方式配置步骤更简单、无需额外安装软件,因此在本次搭建中推荐使用。如果用户想使用multipath 软件来 固定磁盘,请参考达梦《DM8共享存储集群》手册12.2.1环境准备的磁盘准备。
UDEV的作用:Linux系统重启后,磁盘的设备名(如 /dev/vdb)可能会发生变化。UDEV可以根据磁盘的固定属性(如 ID_PATH)给它起一个别名,确保每次启动后都能通过同一个名称(如 /dev/DCR)访问到正确的磁盘。这对于DSC集群至关重要,因为集群配置文件里写的是固定路径。
第一步:查看每块磁盘的ID_PATH:
第二步:创建UDEV规则文件
cat > /etc/udev/rules.d/99-dm-dsc.rules << 'EOF'
# DSC 磁盘绑定规则 - 使用ID_PATH方式(对virtio-blk磁盘更稳定)
SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="pci-0000:07:00.0", SYMLINK+="DCR", OWNER="dmdba", GROUP="dinstall", MODE="0660"
SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="pci-0000:08:00.0", SYMLINK+="VOTE", OWNER="dmdba", GROUP="dinstall", MODE="0660"
SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="pci-0000:09:00.0", SYMLINK+="DMDATA", OWNER="dmdba", GROUP="dinstall", MODE="0660"
SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="pci-0000:0a:00.0", SYMLINK+="DMLOG", OWNER="dmdba", GROUP="dinstall", MODE="0660"
EOF
规则解析:
| 字段 | 值 | 含义 |
|---|---|---|
SUBSYSTEM |
"block" |
匹配块设备子系统(磁盘、存储设备) |
ENV{DEVTYPE} |
"disk" |
匹配整块磁盘(不匹配分区) |
ENV{ID_PATH} |
"pci-0000:07:00.0" |
匹配磁盘的硬件PCI路径(唯一标识) |
SYMLINK |
"DCR" |
创建符号链接 /dev/DCR |
OWNER |
"dmdba" |
设置磁盘所有者为 dmdba |
GROUP |
"dinstall" |
设置磁盘所属组为 dinstall |
MODE |
"0660" |
权限:所有者读写、组读写、其他无权限 |
cat /etc/udev/rules.d/99-dm-dsc.rules
udevadm control --reload-rules
udevadm trigger
ls -l /dev/DCR /dev/VOTE /dev/DMDATA /dev/DMLOG
✅ 绑定成功:
| 符号链接 | 指向 | 大小 | 用途 |
|---|---|---|---|
/dev/DCR |
vdb |
500M | 存储集群配置信息 |
/dev/VOTE |
vdc |
500M | 心跳检测、防止脑裂 |
/dev/DMDATA |
vdd |
20G | 存放数据库数据文件 |
/dev/DMLOG |
vde |
50G | 存放数据库日志文件 |
完成UDEV绑定后,我们按顺序启动了DSC集群的六个服务。这些服务各自承担不同角色,通过不同端口进行通信,具体如下:
| 终端 | 进程名 | 节点名 | 端口 | 作用 |
|---|---|---|---|---|
| 1 | dmcss |
CSS0 | 22201 | 集群主哨兵,监控节点状态 |
| 2 | dmcss |
CSS1 | 22202 | 集群副哨兵,防止脑裂 |
| 3 | dmasmsvr |
ASM0 | 22211 | 主仓库管理员,管理共享磁盘 |
| 4 | dmasmsvr |
ASM1 | 22212 | 副仓库管理员,协同管理磁盘 |
| 5 | dmserver |
DSC1 | 2223 | 二号前台,接受用户连接 |
| 6 | dmserver |
DSC0 | 2221 | 一号前台,接受用户连接 |
vi /home/dmdba/dmdbms/dsc_config/dmdcr_cfg.ini
配置解读:
| 参数 | 值 | 说明 |
|---|---|---|
DCR_N_GRP |
3 | 集群有3个组:CSS、ASM、DB |
DCR_VTD_PATH |
/dev/VOTE |
投票磁盘路径(对应你的vdc) |
DCR_OGUID |
210715 | 集群唯一标识,所有节点必须一致 |
GRP_CSS |
CSS0/CSS1 | 集群控制服务,负责心跳检测 |
GRP_ASM |
ASM0/ASM1 | 自动存储管理,管理共享磁盘 |
GRP_DSC |
DSC0/DSC1 | 数据库实例,对外提供服务 |
dmasvrmal.ini 的作用:配置 ASM(自动存储管理)节点间的 MAL 通信通道。两个 ASM 实例通过这个通道同步磁盘组信息,确保集群存储状态一致。
vi /home/dmdba/dmdbms/dsc_config/dmasvrmal.ini
配置解读:
| 参数 | 值 | 说明 |
|---|---|---|
MAL_INST_NAME |
ASM0 / ASM1 | 必须和 dmdcr_cfg.ini 中的 ASM 节点名一致 |
MAL_HOST |
192.168.200.249 |
MAL 通信使用的 IP 地址 |
MAL_PORT |
22251 / 22252 |
两个 ASM 节点互相通信的端口,不能重复 |
dmdcr.ini DM8手册中提供了更多参数(如自动重启、网络心跳检测),是因为其配置了“全自动”的集群管理模式,CSS可以监控并自动重启故障进程。本次搭建采用的是手动启动模式,因此只配置了CSS启动所必需的5个核心参数。两种方式都可行,手动模式更简单直观,适合学习阶段。
dmdcr.ini 的作用:每个节点自己的 DCR 运行配置文件,相当于节点的"身份证"。它告诉当前节点:
DMDCR_PATH)DMDCR_MAL_PATH)DMDCR_SEQNO)# 创建两个节点的配置目录
mkdir -p /home/dmdba/dmdbms/dsc_config/DSC0
mkdir -p /home/dmdba/dmdbms/dsc_config/DSC1
dmdcr.inivi /home/dmdba/dmdbms/dsc_config/DSC0/dmdcr.ini
dmdcr.inivi /home/dmdba/dmdbms/dsc_config/DSC1/dmdcr.ini
参数解读:
| 参数 | DSC0 值 | DSC1 值 | 说明 |
|---|---|---|---|
DMDCR_PATH |
/dev/dm/asm-dmdcr | /dev/dm/asm-dmdcr |
DCR磁盘路径(两个节点共用同一个) |
DMDCR_MAL_PATH |
dmasvrmal.ini 路径 |
dmasvrmal.ini 路径 |
ASM通信配置文件路径 |
DMDCR_SEQNO |
0 | 1 | 节点序号,必须唯一 |
DMDCR_AUTO_OPEN_CHECK |
111 | 111 | 自动检查 CSS/ASM/DB 全部组件 |
DMDCR_ASM_TRACE_LEVEL |
2 | 2 | ASM日志级别 |
两个节点的区别:只有 DMDCR_SEQNO 不同(0 和 1),其他配置完全相同。
目录结构已经创建好了:
/home/dmdba/dmdbms/dsc_config/
├── dmasvrmal.ini # ASM MAL通信配置(全局)
├── dmdcr_cfg.ini # 集群注册表(全局)
├── DSC0/ # 节点0目录
│ └── dmdcr.ini # 节点0的DCR配置
└── DSC1/ # 节点1目录
└── dmdcr.ini # 节点1的DCR配置
配置文件分类:
dmdcr_cfg.ini、dmasvrmal.ini):描述集群整体拓扑,两个节点共用DSC0/dmdcr.ini、DSC1/dmdcr.ini):每个节点自己的运行配置,通过 DMDCR_SEQNO 区分身份dm.ini 在搭建DSC集群时,我们首先手动创建了一个包含核心参数的 dm.ini 文件,用于指导数据库初始化。当执行 dminit 初始化数据库后,该工具会自动生成一份完整的 dm.ini,其中包含了达梦数据库的所有可配置参数,此前未指定的参数均使用系统默认值。因此,启动数据库时实际使用的是 dminit 生成的完整版配置文件,这份文件也是后续运维和调优的依据。
创建 DSC0/dm.ini:
vi /home/dmdba/dmdbms/dsc_config/DSC0/dm.ini
创建 DSC1/dm.ini:
vi /home/dmdba/dmdbms/dsc_config/DSC1/dm.ini
参数解读:
| 参数 | DSC0 | DSC1 | 说明 |
|---|---|---|---|
INSTANCE_NAME |
DSC0 | DSC1 | 实例名,必须和 dmdcr_cfg.ini 中的 DCR_EP_NAME 一致 |
PORT_NUM |
2221 | 2223 | 数据库对外服务端口(不能重复) |
MAL_PORT |
22261 | 22262 | 数据库实例间MAL通信端口(不能重复) |
LOG_PATH |
+DMLOG/... |
+DMLOG/... |
联机日志路径,存放在ASM磁盘组 |
将两块通过UDEV绑定的裸盘(/dev/DMDATA 和 /dev/DMLOG)标记为ASM磁盘,并分别命名为 DATA0 和 LOG0。
create asmdisk '/dev/DMDATA' 'DATA0'
create asmdisk '/dev/DMLOG' 'LOG0'
说明:这里使用 /dev/DMDATA 和 /dev/DMLOG 是因为:
/dev/DMDATA -> vdd,/dev/DMLOG -> vde)。DCR_EP_ASM_LOAD_PATH 指向的目录里,我们没有把这两个磁盘放进去,但 ASM 需要通过裸设备路径访问它们。
创建一个名为 DMLOG 的磁盘组,并将ASM磁盘 /dev/dm/asm-dmlog 加入其中。执行后使用 lsdg 命令查看,确认 DMDATA 和 DMLOG 两个磁盘组已成功创建,并显示其容量和状态。至此,共享存储已准备就绪,可供后续数据库实例使用。
create diskgroup 'DMLOG' asmdisk '/dev/dm/asm-dmlog'
其中 VOTE 和 DCR 是系统自动创建的,DMDATA 和 DMLOG 是手动创建的,total_file_num: 1 表示磁盘组已经就绪。
磁盘组创建完成后,需要初始化数据库实例,在 ASM 磁盘组上创建真正的 DM 数据库文件,并生成每个 DSC 节点运行需要的配置文件。
dminit.inivi /home/dmdba/dmdbms/dsc_config/dminit.ini
cd /home/dmdba/dmdbms/bin
./dminit control=/home/dmdba/dmdbms/dsc_config/dminit.ini
vi /home/dmdba/dmdbms/dsc_config/dmcssm.ini
# DMCSSM 监视器配置文件
CSSM_OGUID = 210715
CSSM_CSS_IP = 192.168.200.249:22201
CSSM_CSS_IP = 192.168.200.249:22202
CSSM_LOG_PATH = /home/dmdba/dmdbms/log
CSSM_LOG_FILE_SIZE = 512
CSSM_LOG_SPACE_LIMIT = 2048
export ASM_LOAD_PATH=/dev/dm
./dmcss DCR_INI=/home/dmdba/dmdbms/dsc_config/DSC0/dmdcr.ini
export ASM_LOAD_PATH=/dev/dm
./dmcss DCR_INI=/home/dmdba/dmdbms/dsc_config/DSC1/dmdcr.ini
export ASM_LOAD_PATH=/dev/dm
./dmasmsvr DCR_INI=/home/dmdba/dmdbms/dsc_config/DSC0/dmdcr.ini
export ASM_LOAD_PATH=/dev/dm
./dmasmsvr DCR_INI=/home/dmdba/dmdbms/dsc_config/DSC1/dmdcr.ini
export ASM_LOAD_PATH=/dev/dm
./dmserver /home/dmdba/dmdbms/dsc_config/DSC1/dm.ini dcr_ini=/home/dmdba/dmdbms/dsc_config/DSC1/dmdcr.ini
export ASM_LOAD_PATH=/dev/dm
./dmserver /home/dmdba/dmdbms/dsc_config/DSC0/dm.ini dcr_ini=/home/dmdba/dmdbms/dsc_config/DSC0/dmdcr.ini
cd /home/dmdba/dmdbms/bin
export ASM_LOAD_PATH=/dev/dm
./dmserver /home/dmdba/dmdbms/dsc_config/DSC0/dm.ini dcr_ini=/home/dmdba/dmdbms/dsc_config/DSC0/dmdcr.ini
| 组件组 | 节点 | 状态 | 含义 |
|---|---|---|---|
| GRP_CSS | CSS0 | Control Node OPEN, OK |
CSS0 是控制节点,正常运行 |
| CSS1 | Normal Node OPEN, OK |
CSS1 是普通节点,正常运行 | |
| GRP_ASM | ASM0 | Control Node OPEN, OK |
ASM0 是控制节点,正常运行 |
| ASM1 | Normal Node OPEN, OK |
ASM1 是普通节点,正常运行 | |
| GRP_DSC | DSC0 | Control Node OPEN, OK |
DSC0 是控制节点,数据库已打开 |
| DSC1 | Normal Node OPEN, OK |
DSC1 是普通节点,数据库已打开 |
现在测试 DSC 的数据同步(缓存融合)功能。
在当前的 disql连接(DSC0)中执行:
CREATE TABLE test_sync (id INT, name VARCHAR(20));
INSERT INTO test_sync VALUES (1, 'DSC0');
INSERT INTO test_sync VALUES (2, 'DSC0');
COMMIT;
连接到 DSC1:
SELECT * FROM test_sync;
结果:DSC1成功查询到 (1, ‘DSC0’) 和 (2, ‘DSC0’),说明数据已从DSC0同步到DSC1。
在DSC1上插入一条新数据:
INSERT INTO test_sync VALUES (3, 'DSC1');
COMMIT;
切换回DSC0节点,查询测试表:
SELECT * FROM test_sync;
结果:DSC0成功查询到 (3, 'DSC1'),说明数据也能从DSC1同步回DSC0,双向同步正常。
| 测试场景 | 操作节点 | 查询节点 | 结果 |
|---|---|---|---|
| 数据同步 DSC0 → DSC1 | DSC0 插入数据 | DSC1 查询 | ✅ 成功(两条记录全部出现) |
| 数据同步 DSC1 → DSC0 | DSC1 插入数据 | DSC0 查询 | ✅ 成功(新记录出现) |
| 最终数据一致性 | 两个节点共插入3条记录 | 两个节点查询结果一致 | ✅ 完全一致 |
文章
阅读量
获赞
