news 2026/10/15 14:20:29

基于DRBD+Pacemaker+Corosync的MySQL高可用架构实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于DRBD+Pacemaker+Corosync的MySQL高可用架构实战

1. 高可用架构选型背后的思考

1.1 为什么是DRBD而不是共享存储

做过MySQL高可用的朋友都知道,方案大致分两派:共享存储派和复制派。共享存储派里最常见的是SAN或者NAS挂载,但中小团队往往没有独立存储设备,预算和运维成本都扛不住。这时候DRBD就成了一个很务实的选择——它把块设备通过内核模块在网络上做实时镜像,相当于用两台服务器的本地磁盘“拼”出一个逻辑上的共享盘。

我最早接触DRBD是在一个内部业务系统上,当时需求很明确:MySQL不能停超过30秒,预算买不起商业存储,团队只有两个人能维护。DRBD+ Pacemaker + Corosync这套组合就是在这种约束下被选出来的。DRBD负责数据层同步,Pacemaker负责资源调度和决策,Corosync负责集群节点间的通信和心跳。三者各司其职,配合起来能实现MySQL主备加自动切换。

这里要强调一个关键点:DRBD是块设备级别的同步,不是文件级别的。这意味着它对上层应用完全透明,MySQL根本不知道自己的数据目录其实是在一个网络镜像的块设备上。这种透明性带来便利的同时也带来一个隐患——如果DRBD的同步状态出问题,MySQL可能还在正常读写,但数据已经不一致了。所以监控DRBD的磁盘状态是日常运维的重中之重。

1.2 Pacemaker与Corosync的分工逻辑

很多人会把Pacemaker和Corosync混为一谈,其实它们职责完全不同。Corosync管的是“消息层”:节点之间互相发心跳、传集群消息、做成员管理。Pacemaker管的是“决策层”:谁当主、谁当备、资源怎么起停、故障时怎么切换。打个比方,Corosync像是集群里的对讲机系统,Pacemaker像是坐在指挥室里的调度员。

这种分层设计的好处是灵活。Corosync可以换配置、换传输方式,Pacemaker不用动;Pacemaker可以换资源代理、换切换策略,Corosync也不用动。但坏处是排查问题时需要同时看两边的日志,新手容易搞混。我踩过的一个坑就是:Corosync心跳正常,但Pacemaker不切换,最后发现是资源代理脚本里的判断逻辑写错了。

1.3 主备模式与双主模式的取舍

MySQL主备模式下,备库默认不提供写服务,只做只读或者热备。有人会问为什么不搞双主?双主听起来很美,两边都能写,但MySQL的双主在冲突处理上非常麻烦,自增ID、唯一键冲突、数据回环都是坑。而且DRBD本身是单主模式(Primary/Secondary),同一时刻只能有一个节点挂载并读写块设备,这天然就限制了双主的可能性。

所以这套架构的定位很清晰:写操作永远只在一个节点上,备节点处于待命状态。切换发生时,备节点接管VIP、挂载DRBD、启动MySQL。整个过程对应用层来说就是VIP漂移加短暂连接中断,应用重连后继续工作。这种模式牺牲了写扩展性,换来了数据一致性和运维简单性,对大多数中小业务来说是完全划算的。

2. 核心组件细节与实操要点拆解

2.1 DRBD的资源配置与同步模式

DRBD的配置文件通常放在/etc/drbd.d/目录下,每个资源一个.res文件。核心配置项包括resource、device、disk、meta-disk、on节点块、address、port等。下面是一个典型的配置示例:

resource mysql_data { device /dev/drbd0; disk /dev/sdb1; meta-disk internal; on node1 { address 192.168.1.101:7789; node-id 0; } on node2 { address 192.168.1.102:7789; node-id 1; } net { protocol C; cram-hmac-alg sha1; shared-secret "your_secret_here"; } disk { on-io-error detach; fencing resource-only; } }

这里有几个参数值得展开说。protocol C是DRBD的同步复制模式,写操作必须等到本地和远端都确认落盘才返回成功。这是数据安全性最高的模式,但延迟也最大。如果对性能要求极高且能容忍少量数据丢失,可以考虑protocol B(半同步)或protocol A(异步)。我个人的经验是:MySQL场景下除非网络延迟特别大,否则一律用C,数据丢了比性能慢更可怕。

on-io-error detach这个参数很关键。当底层磁盘出现IO错误时,DRBD会自动detach该节点,避免坏盘上的数据继续被同步到对端。如果不设这个,坏盘可能把错误数据扩散出去,那就真的回天乏术了。

meta-disk internal表示元数据存在同一个磁盘的末尾区域。这种方式简单,但要求磁盘末尾预留足够空间。另一种方式是meta-disk /dev/sdc1,把元数据单独放一块盘上,性能更好但多占一个设备。

2.2 Pacemaker的资源栈与约束规则

Pacemaker的资源管理核心是“资源代理”(Resource Agent),常见的有ocf:heartbeat:IPaddr2、ocf:heartbeat:Filesystem、ocf:heartbeat:mysql、ocf:linbit:drbd等。每个资源代理都有自己的参数和状态机,Pacemaker通过调用这些代理来启动、停止、监控资源。

配置资源的基本命令是pcs resource create,比如:

pcs resource create drbd_mysql ocf:linbit:drbd \ drbd_resource=mysql_data \ 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

这里master(新版Pacemaker叫promotable)资源是关键,它定义了DRBD的主从角色。master-max=1表示同一时刻只能有一个节点是Primary,这是DRBD单主模式的硬性要求。

资源创建完之后,必须定义约束规则,否则Pacemaker不知道资源之间的依赖关系和启动顺序。约束分三类:location(位置约束,决定资源倾向在哪个节点)、order(顺序约束,决定资源启动先后)、colocation(共置约束,决定资源是否必须在同一节点)。典型的约束配置如下:

pcs constraint colocation add mysql_vip with ms_drbd_mysql INFINITY with-rsc-role=Master pcs constraint colocation add mysql_fs with mysql_vip INFINITY pcs constraint colocation add mysql_service with mysql_fs INFINITY pcs constraint order promote ms_drbd_mysql then start mysql_fs pcs constraint order start mysql_fs then start mysql_service pcs constraint order start mysql_vip then start mysql_fs

这些约束翻译成人话就是:VIP必须和DRBD主节点在一起,文件系统必须和VIP在一起,MySQL必须和文件系统在一起;启动顺序是先提升DRBD为主,再挂文件系统,再起MySQL,最后配VIP。顺序错了,MySQL可能因为找不到数据目录而启动失败。

2.3 Corosync的通信配置与心跳机制

Corosync的配置文件是/etc/corosync/corosync.conf,核心是totem块。下面是一个双节点配置:

totem { version: 2 cluster_name: mysql_cluster transport: knet crypto_cipher: aes256 crypto_hash: sha256 token: 3000 token_retransmits_before_loss_const: 10 join: 60 consensus: 3600 max_messages: 20 interface { ringnumber: 0 bindnetaddr: 192.168.1.0 mcastport: 5405 ttl: 1 } } quorum { provider: corosync_votequorum expected_votes: 2 two_node: 1 } logging { fileline: off to_stderr: yes to_logfile: yes logfile: /var/log/corosync/corosync.log to_syslog: yes debug: off timestamp: on logger_subsys { subsys: QUORUM debug: off } }

token参数决定心跳超时时间,默认3000毫秒。如果网络抖动大,可以适当调大,但调太大意味着故障检测变慢。consensus是共识超时,通常是token的1.2倍左右。two_node: 1是双节点集群的特殊配置,告诉Corosync只有两个节点,避免脑裂时无法形成多数派。

注意:双节点集群没有真正的多数派,所以必须配合fencing设备(如IPMI、PDU)或者resource-onlyfencing策略,否则脑裂时两边都以为自己是主,数据就乱了。

2.4 MySQL在集群中的启动脚本适配

Pacemaker自带的ocf:heartbeat:mysql代理可以直接用,但有几个参数必须根据实际环境调整:

pcs resource create mysql_service ocf:heartbeat:mysql \ binary=/usr/sbin/mysqld \ config=/etc/my.cnf \ datadir=/var/lib/mysql \ socket=/var/lib/mysql/mysql.sock \ pid=/var/run/mysqld/mysqld.pid \ log=/var/log/mysqld.log \ user=mysql \ test_user=root \ test_passwd=your_password \ test_table=mysql.user \ op monitor interval=20s timeout=30s \ op start timeout=120s interval=0 \ op stop timeout=120s interval=0

test_user和test_passwd是监控用的账号密码,Pacemaker会定期用这个账号连MySQL执行SELECT来确认服务健康。test_table指定监控查询的表,一般用mysql.user就行。op monitor的timeout要设得比MySQL正常响应时间长,否则网络稍微慢一点就误判为故障。

还有一个容易忽略的点:MySQL的datadir必须和DRBD挂载点一致。比如DRBD挂载到/data,那datadir就应该是/data/mysql,而不是默认的/var/lib/mysql。这个路径在my.cnf里也要同步改,否则切换后备节点启动MySQL会找不到数据。

3. 完整实操流程与关键环节实现

3.1 环境准备与基础软件安装

假设有两台服务器,主机名分别是node1和node2,操作系统是常见的Linux发行版。每台机器除了系统盘外,额外挂一块数据盘/dev/sdb,用来做DRBD的底层设备。

第一步,配置主机名和hosts解析:

hostnamectl set-hostname node1 echo "192.168.1.101 node1" >> /etc/hosts echo "192.168.1.102 node2" >> /etc/hosts

第二步,安装必要软件包。不同发行版包名略有差异,以常见的包管理器为例:

# 安装DRBD、Pacemaker、Corosync及相关工具 yum install -y drbd90-utils kmod-drbd90 pacemaker corosync pcs fence-agents-all

或者:

apt install -y drbd-utils pacemaker corosync pcs fence-agents

第三步,加载DRBD内核模块并设置开机自启:

modprobe drbd echo "drbd" >> /etc/modules-load.d/drbd.conf

第四步,初始化数据盘。两块盘都要做,且分区大小要完全一致:

parted /dev/sdb mklabel gpt parted /dev/sdb mkpart primary 0% 100%

3.2 DRBD资源初始化与首次同步

在两台机器上都创建/etc/drbd.d/mysql_data.res,内容如前面2.1节所示。然后执行初始化:

drbdadm create-md mysql_data drbdadm up mysql_data

这时候DRBD应该处于Connected但Secondary/Secondary状态。接下来在node1上执行首次同步:

drbdadm primary --force mysql_data

这个命令会把node1设为Primary,并开始把本地数据同步到node2。同步时间取决于磁盘大小和网络带宽,100GB的数据在千兆网络下大概需要20到30分钟。可以用drbdadm status或者cat /proc/drbd查看同步进度。

实操心得:首次同步期间不要做任何写操作,也不要在DRBD设备上创建文件系统。等两边都显示UpToDate之后再继续。如果同步卡住,先检查网络连通性和防火墙规则,DRBD默认用7789端口。

同步完成后,在node1上创建文件系统并挂载:

mkfs.ext4 /dev/drbd0 mkdir /data mount /dev/drbd0 /data

然后把MySQL的数据目录迁移到/data/mysql,并修改my.cnf中的datadir。确认MySQL能正常启动后,卸载文件系统,把DRBD降为Secondary:

umount /data drbdadm secondary mysql_data

3.3 集群初始化与资源栈配置

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

systemctl enable --now corosync systemctl enable --now pacemaker

然后在任意一台机器上设置集群认证并启动集群:

passwd hacluster pcs cluster auth node1 node2 -u hacluster -p your_password pcs cluster setup --name mysql_cluster node1 node2 pcs cluster start --all pcs cluster enable --all

检查集群状态:

pcs status

应该能看到两个节点都是Online,并且有Quorum。接下来按顺序创建资源:

# 1. 创建DRBD主从资源 pcs resource create drbd_mysql ocf:linbit:drbd \ drbd_resource=mysql_data \ op monitor interval=15s role=Master \ op monitor interval=30s role=Slave pcs resource promotable drbd_mysql \ master-max=1 master-node-max=1 \ clone-max=2 clone-node-max=1 \ notify=true # 2. 创建文件系统资源 pcs resource create mysql_fs ocf:heartbeat:Filesystem \ device=/dev/drbd0 \ directory=/data \ fstype=ext4 \ op monitor interval=20s timeout=40s # 3. 创建VIP资源 pcs resource create mysql_vip ocf:heartbeat:IPaddr2 \ ip=192.168.1.100 \ cidr_netmask=24 \ op monitor interval=10s # 4. 创建MySQL资源 pcs resource create mysql_service ocf:heartbeat:mysql \ binary=/usr/sbin/mysqld \ config=/etc/my.cnf \ datadir=/data/mysql \ socket=/data/mysql/mysql.sock \ pid=/var/run/mysqld/mysqld.pid \ log=/var/log/mysqld.log \ user=mysql \ test_user=root \ test_passwd=your_password \ test_table=mysql.user \ op monitor interval=20s timeout=30s \ op start timeout=120s interval=0 \ op stop timeout=120s interval=0

最后添加约束:

pcs constraint colocation add mysql_vip with master drbd_mysql INFINITY with-rsc-role=Master pcs constraint colocation add mysql_fs with mysql_vip INFINITY pcs constraint colocation add mysql_service with mysql_fs INFINITY pcs constraint order promote drbd_mysql then start mysql_fs pcs constraint order start mysql_fs then start mysql_vip pcs constraint order start mysql_vip then start mysql_service

配置完成后,Pacemaker会自动在某个节点上启动所有资源。用pcs status确认所有资源都在同一个节点上运行,且DRBD处于Master状态。

3.4 手动切换与自动切换验证

手动切换是验证集群配置是否正确的最直接方式。执行:

pcs resource move mysql_service node2

Pacemaker会按顺序停止MySQL、卸载文件系统、降级DRBD、释放VIP,然后在node2上反向操作。整个过程大概需要30到60秒。切换完成后,用pcs status确认资源都在node2上,并且VIP能ping通,MySQL能连接。

自动切换的验证稍微麻烦一点。最安全的方式是模拟MySQL进程崩溃:

# 在MySQL所在节点上执行 killall -9 mysqld

Pacemaker的监控会在20秒内发现MySQL不可用,然后触发切换。如果配置正确,资源会自动漂移到另一个节点。这里要注意:killall -9只是杀进程,不模拟节点宕机。如果要模拟节点宕机,可以用echo c > /proc/sysrq-trigger,但这会导致内核崩溃,测试环境可以玩,生产环境千万别试。

避坑技巧:自动切换测试前,先把pcs property set stonith-enabled=false,否则没有fencing设备时集群会拒绝切换。测试完再根据实际情况决定是否开启STONITH。

4. 常见问题与排查技巧实录

4.1 DRBD状态异常排查速查表

现象可能原因排查命令解决方法
StandAlone网络不通或端口被防火墙拦截drbdadm status、ss -tlnp | grep 7789检查防火墙规则,确保7789端口双向放行
WFConnection对端节点DRBD未启动systemctl status drbd在对端执行drbdadm up mysql_data
SyncTarget长时间不变同步速度慢或磁盘IO瓶颈cat /proc/drbd、iostat -x 1检查网络带宽和磁盘负载,必要时限速同步
Diskless底层磁盘故障或detachdmesg | grep drbd检查磁盘健康状态,修复后重新attach
两边都是Primary脑裂drbdadm status手动干预,选择数据新的一方强制Primary,另一方丢弃数据重新同步

脑裂是DRBD最危险的状态。一旦发生,必须人工介入,不能自动恢复。处理原则是:选一个数据最新的节点作为Primary,另一个节点执行drbdadm connect --discard-my-data mysql_data,然后重新同步。丢数据的那一方如果有重要变更,那就真的丢了,所以fencing设备在这套架构里不是可选项,而是必选项。

4.2 Pacemaker资源启动失败常见原因

MySQL资源启动失败是最常见的问题,八成以上是路径或权限问题。Pacemaker的日志在/var/log/pacemaker/pacemaker.log,资源代理的日志在/var/log/cluster/下面。排查时先看pcs status里资源的FAILED原因,再去对应日志里找详细报错。

一个很隐蔽的坑是SELinux。如果系统开了SELinux,Pacemaker启动MySQL时可能被拒绝访问/data目录。临时用setenforce 0验证,如果问题消失,就需要给/data目录打上正确的SELinux标签,或者干脆把SELinux设为permissive。

另一个坑是mysql.sock路径。Pacemaker的MySQL代理默认用/var/lib/mysql/mysql.sock,但我们的数据目录在/data/mysql,socket路径必须显式指定,否则监控会失败,导致资源被反复重启。

4.3 切换后应用连接不上的处理思路

切换完成后,VIP漂移过去了,MySQL也起来了,但应用还是连不上。这种情况通常有三个原因:第一,应用配置的是固定IP而不是VIP;第二,MySQL的用户权限里没有允许从VIP所在网段连接;第三,防火墙没有放行VIP的3306端口。

我遇到过一次很诡异的情况:VIP能ping通,telnet 3306也通,但应用就是报连接超时。最后发现是MySQL的bind-address配置成了127.0.0.1,只监听本地回环。切换后新节点上的MySQL同样只监听本地,外部连接自然进不来。把bind-address改成0.0.0.0或者VIP地址就好了。

实操心得:每次切换后,除了检查pcs status,一定要用mysql -h VIP -u user -p从外部客户端实际连一次。Pacemaker说资源健康,不代表应用能正常访问。

4.4 性能调优与日常维护建议

DRBD的同步会占用网络带宽和磁盘IO,如果业务写入量大,建议把DRBD的同步限速打开,避免同步流量把业务流量挤掉。在资源配置里加:

disk { c-plan-ahead 0; c-fill-target 24M; c-min-rate 80M; c-max-rate 720M; }

这些参数控制DRBD的同步速率,c-max-rate是上限,c-min-rate是下限。具体数值要根据实际带宽和业务负载调整,没有万能公式。

日常维护方面,建议每天检查一次drbdadm status和pcs status,每周做一次手动切换演练。演练不是走过场,要真的把业务切过去跑一段时间再切回来,这样才能发现配置里隐藏的问题。我见过太多集群配好之后从来没切过,真出故障时才发现切换脚本有bug,那就被动了。

5. 这套架构的适用边界与扩展思路

5.1 什么场景适合这套方案

DRBD+Pacemaker+Corosync这套组合最适合的是:预算有限、团队规模小、对数据一致性要求高、能接受秒级到分钟级切换时间的场景。比如内部管理系统、中小型电商后台、日志分析平台等。它的优势是全部基于开源软件,没有License费用,架构透明可控,出了问题能自己排查。

但它也有明显的边界。第一,它不适合跨机房部署,DRBD的同步对网络延迟非常敏感,同城双活勉强可以,异地灾备基本不可行。第二,它不适合写压力极大的场景,因为单主模式下写能力受限于单台服务器。第三,它不适合需要读写分离和水平扩展的场景,那应该考虑MySQL Group Replication或者基于中间件的分库分表方案。

5.2 从主备到多节点的演进路径

如果业务增长到单台MySQL扛不住写压力,这套架构就需要演进。一个常见的路径是:保留DRBD+Pacemaker做底层高可用,上层用MySQL的主从复制做读写分离。写请求走VIP到主库,读请求通过多个从库分担。从库可以部署在独立的服务器上,不参与DRBD集群。

另一个路径是引入ProxySQL或者类似中间件,把应用和数据库解耦。应用连ProxySQL,ProxySQL根据后端MySQL的健康状态自动路由。这样即使Pacemaker切换时VIP短暂不可用,ProxySQL也能快速感知并切换到新的主库,应用层几乎无感。

5.3 监控告警的关键指标

这套架构要监控的指标比单机MySQL多得多。除了常规的MySQL连接数、QPS、慢查询之外,还必须监控:DRBD的复制状态(Connected还是StandAlone)、DRBD的磁盘状态(UpToDate还是Inconsistent)、Pacemaker的节点状态和资源状态、Corosync的Quorum状态、VIP是否可达。

我一般会在每台节点上部署一个轻量级的监控代理,定期采集这些指标并推送到监控系统。告警规则里,DRBD状态异常和Pacemaker资源失败是最高优先级,必须第一时间处理。VIP不可达次之,因为可能只是切换过程中的短暂现象。

最后分享一个小技巧:在Pacemaker里配置一个notification资源,当资源状态变化时自动发邮件或者调用Webhook。这样切换发生时你能立刻知道,而不是等用户报障才发现。具体做法是创建一个ocf:heartbeat:MailTo资源,绑定到集群的notify事件上。虽然配置稍微麻烦一点,但关键时刻能省很多事。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 14:20:19

C++调用命令行程序的三种方法:从Shell重定向到Boost.Process实战

1. 项目概述:为什么命令行输出重定向不是“写个 > 就完事”的小事在 Windows 开发、自动化脚本、CI/CD 流水线或本地工具链集成中,我几乎每天都要和cmd.exe打交道——不是为了怀旧,而是因为很多老旧但关键的内部工具、硬件驱动配套程序、第…

作者头像 李华
网站建设 2026/10/15 14:19:46

Windows Server 2012 R2 内网离线安装 IIS 实战指南

简介:这份资源是面向IT运维人员与系统管理员的Windows Server 2012 R2 IIS离线安装包,用于在无外网或网络受限的服务器环境中添加、更新IIS角色与相关组件,解决内网部署Web服务时无法在线拉取源文件的问题。压缩包共1568个文件,约…

作者头像 李华
网站建设 2026/10/15 14:19:30

GESP五级贪心算法全解:从区间调度到堆优化,掌握考点与避坑技巧

我把GESP五级的真题和模拟题翻来覆去做过好几遍之后,发现一个特别明显的规律:凡是考算法思想的大题,十道里至少有六道能闻到贪心的味道。考生圈子里甚至流传着一句话——五级能不能过,很大程度上看贪心学得透不透。这个说法不算夸…

作者头像 李华
网站建设 2026/10/15 14:18:28

本地知识库语义检索实战:Docker部署PGVector与MCP服务

1. 为什么要在本地给 WorkBuddy 配一套向量库WorkBuddy 这类本地知识库工具,核心能力是把散落在本地的文档、笔记、代码片段变成可检索、可对话的知识资产。但很多人用着用着会发现一个瓶颈:纯关键词检索越来越不够用。你搜“部署流程”,它只…

作者头像 李华
网站建设 2026/10/15 14:18:22

SpringBoot2+Vue3宠物领养系统实战拆解:从架构设计到功能落地

做一个完整项目最大的痛点不是“不会敲代码”,而是“不知道整个系统该怎么串起来”。很多同学学完Java基础、SpringBoot、Vue,真到自己动手做一个带前后端的完整项目时,还是容易卡壳:表结构怎么设计、接口怎么分层、前端怎么对接、…

作者头像 李华
网站建设 2026/10/15 14:18:01

软件测试工程师英语面试全攻略:从测试逻辑到高频问答模板

简介:软件测试工程师的英语面试,除了考察技术功底,更考验表达与临场心理。这份资料呈现了完整的准备思路:先备好高质量的自我介绍,再熟悉面试官用英语闲聊测试工作经历的常见问法,并学会遥控器、自动选款机…

作者头像 李华