☰
MySQL高可用方案:DRBD+Pacemaker+Corosync实现数据零丢失自动切换
2026/10/15 14:20:28 网站建设 项目流程

1. 为什么要在 MySQL 高可用里选 DRBD 这套组合

1.1 从一次真实的故障切换说起

几年前我接手过一套内部订单系统的数据库运维,单机 MySQL 跑了两年多,硬盘一坏就是半天停机,业务方电话打爆。后来我们决定上高可用,评估过主从复制加中间件、共享存储加集群文件系统、以及 DRBD 加 Pacemaker 加 Corosync 这几条路线。最后选了 DRBD 这套,原因很直接:我们的数据量不大(当时不到 200G),写入 QPS 峰值也就几千,但对数据一致性要求极高,不能容忍主从复制那种异步延迟导致的数据丢失。

DRBD 的本质是块设备级别的同步复制。你可以把它理解成两台服务器之间架了一根"虚拟的数据线",主节点写什么,从节点在块层面同步什么。它工作在操作系统内核的块设备层,MySQL 根本感知不到底下是本地盘还是网络盘。这一点很关键,因为这意味着 MySQL 不需要做任何改造,binlog、redo log、数据文件全部照常写,DRBD 在下面默默把每个块的变化复制到对端。

Pacemaker 和 Corosync 是这套方案的大脑和神经。Corosync 负责集群成员之间的心跳通信和消息传递,Pacemaker 负责根据资源状态做决策——谁当主、谁当备、什么时候切换、切换时先停什么后起什么。三者配合起来,才能实现"MySQL 主备加自动切换"这个目标。

1.2 这套方案到底解决了什么问题

单机 MySQL 的痛点很明确:硬件故障、系统崩溃、人为误操作,任何一个环节出问题都是长时间停机。传统主从复制虽然能做备份,但切换需要人工介入,而且异步复制存在数据丢失窗口。DRBD 方案的核心价值在于三点:

第一,数据零丢失。DRBD 支持协议 C(同步复制),主节点写操作必须等到从节点确认落盘才返回成功。这意味着即使主节点瞬间断电,从节点上的数据也是完整的。

第二,自动切换。Pacemaker 持续监控 MySQL 和 DRBD 的状态,主节点挂掉后自动在备节点提升 DRBD 为主、启动 MySQL、接管虚拟 IP,整个过程通常几十秒内完成,不需要人工登录操作。

第三,对应用透明。应用连接的是虚拟 IP,切换后 IP 漂移到新主节点,应用重连即可,不需要改配置。

1.3 适合什么样的场景,不适合什么样的场景

这套方案不是万能的,我踩过坑之后总结出它的适用边界。适合的场景:数据量在几百 G 以内、写入量中等、对数据一致性要求极高、预算有限不想买商业存储、团队有一定 Linux 运维基础。不适合的场景:数据量上 T 且持续增长、写入 QPS 极高(DRBD 同步复制的网络延迟会成为瓶颈)、跨机房容灾(DRBD 对网络延迟敏感,同城双活勉强,异地基本不可行)。

还有一个容易被忽略的点:DRBD 是块设备复制,从节点上的文件系统在备状态时是不可挂载的。也就是说你不能在备节点上直接读 MySQL 数据做报表查询。如果需要读写分离,这套方案满足不了,得另想办法。

2. 核心组件原理与关键参数拆解

2.1 DRBD 的工作机制与复制协议选择

DRBD 在每台节点上表现为一个块设备,比如 /dev/drbd0。它底层对应一块真实的磁盘分区或 LVM 逻辑卷,上层再放文件系统。数据流向是这样的:MySQL 写文件系统,文件系统写到 /dev/drbd0,DRBD 内核模块拦截写请求,一份写本地磁盘,一份通过网络发到对端。

复制协议有三个选项,这是选型时第一个要拍板的事:

协议行为数据安全性性能影响
协议 A主节点写本地成功即返回,异步发往从节点可能丢数据最低
协议 B主节点写本地成功且从节点收到数据(未落盘)后返回切换时可能丢中等
协议 C主节点和从节点都确认落盘后才返回零丢失最高

我们选的是协议 C。代价是每次写都要等网络往返,实测在千兆内网、同机房环境下,写延迟增加约 0.3 到 0.8 毫秒。对于我们的业务完全可接受。如果你的业务对延迟极度敏感,需要慎重评估,或者考虑用 SSD 加万兆网卡来压低这个开销。

2.2 Pacemaker 的资源管理逻辑

Pacemaker 里一切皆资源。MySQL 是一个资源,DRBD 是一个资源,虚拟 IP 是一个资源。资源之间有依赖关系和启动顺序,这是配置的核心难点。

拿我们的场景举例,依赖链是这样的:DRBD 主资源必须先就绪,文件系统才能挂载;文件系统挂载后,MySQL 才能启动;MySQL 启动后,虚拟 IP 才能对外服务。Pacemaker 用约束(constraint)来描述这些关系,包括顺序约束(order)、位置约束(location)、协同约束(colocation)。

顺序约束决定"谁先谁后",比如 DRBD 提升为主之后才能挂文件系统。协同约束决定"谁和谁必须在一起",比如 MySQL 必须和 DRBD 主资源在同一节点。位置约束决定"谁倾向于在哪",比如可以设置某节点优先级更高。

我一开始没搞清协同约束,结果出现过 MySQL 在 A 节点、DRBD 主在 B 节点的诡异状态,MySQL 直接起不来。后来才明白,必须用 colocation 把 MySQL、文件系统、DRBD 主资源绑死在一起。

2.3 Corosync 的心跳与仲裁

Corosync 负责集群通信,最核心的是心跳机制。节点之间定期互发心跳包,超过设定时间收不到就判定对方失联。这里有个经典问题叫"脑裂"(split-brain):两个节点都认为对方挂了,各自把自己提升为主,数据就分叉了。

防脑裂的手段有两层。第一层是 Corosync 的冗余通信通道,我们配了两条心跳链路,一条走业务网,一条走单独的直连网线,任何一条通就不会误判。第二层是 DRBD 自己的脑裂检测,一旦发现两个节点都试图当主,会拒绝服务并记录到日志,需要人工介入恢复。

仲裁方面,两节点集群没有天然仲裁者,我们加了一个轻量的仲裁设备(quorum device),避免一个节点失联时另一个节点无法获得多数票而拒绝服务。这个细节很多教程不讲,但两节点集群不配仲裁,切换行为会很不稳定。

3. 从零搭建的完整实操过程

3.1 环境规划与基础准备

先明确我们的模拟环境。两台服务器,主机名分别叫 node-a 和 node-b,操作系统用主流的 Linux 发行版。每台机器两块网卡,一块业务网,一块心跳直连。磁盘方面,每台机器留一块独立分区或 LVM 卷专门给 DRBD 用,大小必须完全一致。

基础准备清单:

  • 两台机器时间同步,用 chrony 或 ntp,时间偏差会导致集群通信异常
  • 主机名和 hosts 解析配好,集群节点之间必须能通过主机名互相解析
  • 关闭防火墙或放行必要端口:Corosync 用 5405 UDP,DRBD 用 7789 TCP
  • 确认内核加载了 DRBD 模块,modprobe drbd后lsmod | grep drbd能看到
  • 安装软件包:drbd 相关工具、pacemaker、corosync、资源代理(resource-agents)

注意:两台机器的 DRBD 版本、Pacemaker 版本尽量保持一致,版本差异会导致协议不兼容,我吃过这个亏,排查了大半天。

3.2 DRBD 配置详解

DRBD 的主配置文件通常在 /etc/drbd.d/ 目录下,我们建一个 mysql.res 文件。核心配置分三块:resource 定义、on 节点定义、net 网络参数。

resource mysql { protocol C; device /dev/drbd0; disk /dev/sdb1; meta-disk internal; on node-a { address 10.0.0.1:7789; } on node-b { address 10.0.0.2:7789; } net { cram-hmac-alg sha1; shared-secret "your-secret-here"; after-sb-0pri discard-zero-changes; after-sb-1pri discard-secondary; after-sb-2pri disconnect; } }

逐项解释关键参数。protocol C就是前面说的同步复制。meta-disk internal表示元数据存在数据盘内部,省事但会占用一点空间。cram-hmac-alg和shared-secret是节点间认证,防止未授权节点接入。

after-sb-*这几个参数是脑裂后的自动恢复策略,非常重要。after-sb-0pri discard-zero-changes表示双方都没有改动的脑裂,直接丢弃零改动方。after-sb-1pri discard-secondary表示一方有改动一方没有,丢弃没改动的那方。after-sb-2pri disconnect表示双方都有改动,这种情况最危险,直接断开不自动恢复,必须人工判断哪边数据是对的。这个策略是保守但安全的,宁可人工介入也不能自动选错。

初始化流程:

# 两台机器都执行,创建元数据 drbdadm create-md mysql # 两台机器都启动 DRBD 服务 systemctl start drbd # 在 node-a 上提升为主 drbdadm primary mysql --force # 查看状态,确认 Primary/Secondary 且 uptodate cat /proc/drbd

第一次提升主用--force,因为初始状态两边都是不一致的,需要强制指定一方为主进行初始同步。同步完成后,cat /proc/drbd应该看到两个节点都是UpToDate。

3.3 文件系统与 MySQL 数据目录

DRBD 主资源就绪后,在 node-a 上格式化并挂载:

mkfs.ext4 /dev/drbd0 mkdir -p /data/mysql mount /dev/drbd0 /data/mysql

然后把 MySQL 的数据目录指向 /data/mysql。如果是新装 MySQL,初始化时指定 datadir 即可。如果是迁移已有数据,先停 MySQL,把原数据目录内容 rsync 到 /data/mysql,再改配置。

实操心得:文件系统建议用 ext4 或 xfs,两者在 DRBD 上表现都稳定。不要用 btrfs,我试过在切换时出现过挂载异常。另外挂载参数加上noatime,减少不必要的写操作,能降低 DRBD 同步压力。

3.4 Pacemaker 集群初始化与资源配置

先在两台机器上启动 Corosync 和 Pacemaker:

systemctl start corosync systemctl start pacemaker

然后在任一节点上做集群初始化:

# 设置集群认证密码 passwd hacluster # 认证并启动集群 pcs cluster auth node-a node-b pcs cluster setup --name mysql_cluster node-a node-b pcs cluster start --all pcs cluster enable --all

接下来配置资源。先配 DRBD 资源,用 pacemaker 自带的 drbd 资源代理:

pcs resource create drbd_mysql ocf:linbit:drbd \ drbd_resource=mysql \ op monitor interval=15s role=Master \ op monitor interval=30s role=Slave

然后配置主从资源:

pcs resource master ms_drbd_mysql drbd_mysql \ master-max=1 master-node-max=1 \ clone-max=2 clone-node-max=1 \ notify=true

接着配置文件系统、MySQL、虚拟 IP:

pcs resource create fs_mysql Filesystem \ device=/dev/drbd0 directory=/data/mysql fstype=ext4 pcs resource create vip_mysql IPaddr2 ip=10.0.0.100 pcs resource create mysql_service systemd:mysqld \ op monitor interval=20s

最后配置约束,这是让整套系统正确运转的关键:

# 顺序:DRBD 主 -> 文件系统 -> MySQL -> VIP pcs constraint order promote ms_drbd_mysql then fs_mysql pcs constraint order fs_mysql then mysql_service pcs constraint order mysql_service then vip_mysql # 协同:文件系统、MySQL、VIP 必须和 DRBD 主在同一节点 pcs constraint colocation add fs_mysql with ms_drbd_mysql INFINITY pcs constraint colocation add mysql_service with fs_mysql INFINITY pcs constraint colocation add vip_mysql with mysql_service INFINITY

配置完成后pcs status应该看到所有资源正常启动,DRBD 主在某一节点,其余资源跟随。

3.5 切换测试与验证

配置完不测试等于没配。我们做了三类测试。

第一类,手动切换。pcs node standby node-a,观察资源是否平滑迁移到 node-b。正常情况几十秒内完成,VIP 漂移,MySQL 在新节点启动。

第二类,模拟主节点宕机。直接echo b > /proc/sysrq-trigger强制重启 node-a,看 node-b 是否自动接管。这个测试最接近真实故障。

第三类,模拟 MySQL 进程崩溃。kill -9掉 mysqld 进程,看 Pacemaker 是否检测到并触发切换。

每次测试后都要验证数据完整性,在切换前后各插入一条带时间戳的记录,切换后查询确认数据没丢。

4. 常见问题排查与避坑经验

4.1 脑裂的识别与恢复

脑裂是这套方案最危险的状态。识别方法:cat /proc/drbd看到两个节点都是Primary,或者日志里出现Split-Brain detected。一旦脑裂,DRBD 会停止服务,MySQL 也起不来。

恢复步骤必须谨慎。首先确认哪边的数据是新的,可以通过对比 binlog 位置或者业务数据时间戳判断。假设 node-a 数据新,node-b 数据旧:

# 在 node-b 上放弃自己的数据 drbdadm secondary mysql drbdadm connect --discard-my-data mysql # 在 node-a 上重新连接 drbdadm connect mysql

注意:--discard-my-data会丢弃该节点所有数据,执行前务必确认清楚哪边是正确数据。我见过有人搞反了,把新数据覆盖掉,损失惨重。

4.2 切换后 MySQL 起不来的排查

切换后 MySQL 启动失败是最常见的故障。排查顺序:先看 DRBD 是否成功提升为主,cat /proc/drbd确认;再看文件系统是否挂载,df -h确认;最后看 MySQL 错误日志,通常在数据目录下的 .err 文件。

常见原因有几个。一是文件系统没挂上,MySQL 找不到数据目录。二是权限问题,切换后文件属主变了,MySQL 用户读不了。三是 MySQL 的 pid 文件或 socket 文件残留,导致启动冲突。针对第三种,可以在 MySQL 配置里把 pid 和 socket 放到非 DRBD 的本地目录,避免切换时残留。

4.3 性能调优的几个关键点

DRBD 同步复制的性能瓶颈通常在网络和磁盘。我们做过几轮调优,效果比较明显的措施:

  • 网卡开启巨帧(MTU 9000),减少网络包处理开销
  • DRBD 的sndbuf-size和rcvbuf-size调大,默认值在高吞吐下不够用
  • 用 SSD 做 DRBD 底层存储,机械盘在同步复制下延迟明显
  • MySQL 的innodb_flush_log_at_trx_commit保持 1,不要为了性能改成 2,否则 DRBD 的零丢失优势就没了

调优前后我们做了对比测试,同样压力下,优化后写延迟从平均 1.2 毫秒降到 0.5 毫秒左右。

4.4 常见问题速查表

现象可能原因排查方向
资源无法启动约束配置错误pcs constraint show检查依赖
DRBD 一直 Inconsistent初始同步未完成等待同步,查看同步进度
切换后 VIP 不通IP 资源未启动pcs status看 VIP 状态
MySQL 反复重启资源监控间隔太短调大 monitor interval
集群节点失联心跳网络故障检查 Corosync 日志和网卡
脑裂后无法恢复恢复策略配置检查 after-sb 参数

5. 这套方案的运维日常与个人体会

5.1 日常巡检要看什么

集群稳定运行后,日常巡检不能省。我每天会看几个东西:pcs status确认所有资源正常、cat /proc/drbd确认同步状态是 UpToDate、MySQL 错误日志有没有异常、DRBD 日志有没有同步延迟告警。另外定期做一次计划内切换演练,保持团队对切换流程的熟悉度,真出事的时候才不会手忙脚乱。

监控方面,我们把 Pacemaker 的资源状态、DRBD 的同步状态和延迟、MySQL 的连接数和慢查询都接入了监控系统,设置阈值告警。特别是 DRBD 的同步延迟,一旦持续升高说明底层存储或网络有问题,要提前处理。

5.2 我踩过的几个坑

第一个坑是没配仲裁设备。两节点集群在单节点故障时,剩下的节点因为拿不到多数票会拒绝服务,结果就是该切换的时候切不了。加了仲裁设备后这个问题解决。

第二个坑是 MySQL 的 socket 文件放在 DRBD 目录里。切换时旧 socket 残留,新节点启动 MySQL 报地址已占用。后来把 socket 和 pid 都挪到本地目录,问题消失。

第三个坑是没做切换演练就直接上生产。有一次真实故障触发切换,结果因为一个约束配置的小错误,切换卡住了。从那以后我坚持每次变更后都做一次完整的切换测试。

5.3 后续可以怎么扩展

这套基础架构搭好后,有几个方向可以继续完善。一是加第三个节点做仲裁和只读查询,缓解两节点的仲裁压力。二是把 DRBD 的底层存储换成 LVM,方便在线扩容。三是结合备份工具做定期全量和增量备份,毕竟 DRBD 只防硬件故障,防不了误删数据,误删会同步到两个节点。

如果数据量增长到 DRBD 扛不住的程度,可以考虑迁移到分布式存储或者商业高可用方案。但就我这些年的经验,对于中小规模、强一致要求的场景,DRBD 加 Pacemaker 加 Corosync 这套组合依然是性价比很高的选择,稳定、可控、不依赖外部服务,出了问题自己就能排查到底层。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询