☰
MPP主备搭建实战:协调节点与数据节点高可用
2026/10/22 11:33:54 网站建设 项目流程

接到“MPP 主备搭建”这个任务时,不少人的第一反应都是:两台机器、配上主从复制、坏了自动切换,这套东西单机数据库早就玩透了。但真上过生产环境以后你会发现,MPP的主备和单机主备根本不是一回事。难点不在于复制怎么做,而在于MPP架构里天然有两类节点:协调节点和数据节点,它们各自都有一份独立的容灾诉求,哪一层没考虑到位,故障真正发生的时候照样会让你在会议室里对着大屏发呆。

这篇文章围绕一个基于PostgreSQL内核的经典MPP架构来写实操,命令我会尽量用通用管理员工具的方式给出,你在自己的发行版环境里基本都能对上号。适合两类人看:第一类是正在搭集群、想找一个完整主备搭建参考的DBA和运维;第二类是集群已经跑起来、但总觉得没做过故障演练心里没底的同学。看完之后至少能回答一个问题:MPP的主备,到底备了什么,以及怎么确保切换的时候真的能起来。

1. MPP主备到底在“备”什么:先把架构拆干净

1.1 从单机主备到MPP主备,不是简单加一台机器

单机主备的逻辑很好懂:一个实例两份数据,主库产生WAL,备库拿过去回放,主库挂了备库顶上。但MPP数据库对“高可用”的要求比这个苛刻得多。

MPP里,客户端看到的唯一入口叫协调节点(Coordinator),它负责接收SQL、生成分布式执行计划、维护全局元数据,但业务数据并不保存在协调节点上。用户的一行行真实数据,是被切片打散到若干个数据节点(Segment)上的,每个数据节点在物理上也是一个数据库实例。这就导致主备这件事裂成了两层:

  • 协调节点是单点:所有会话都从它进来,它一旦故障,即使所有数据节点活着,新SQL也进不来。
  • 每个数据分片也是单点:比如某个Segment的primary实例崩溃了,包在它身上那一部分数据对外就不可访问,协调节点再怎么健康也救不回来。

很多新手第一次搭MPP主备时最容易犯的认知错误,是把“备协调节点”当成“全库备份”。以为协调节点有备了,数据就都有容灾了。实际上协调节点只是“大脑备份”,它同步的是元数据,不是用户分片数据;真正挡在数据丢失前面的,是每个数据分片自己的镜像副本。

打个比方你就明白了:协调节点是公司前台,负责登记访客、引导流程,但自己不保存业务档案;每个数据节点是各业务部门的档案室,档案室里同一份卷宗有一式两份,正本放A柜,影印本放B柜。前台休假的替代员工能做的事,和某个档案室正本被烧后影印本顶上来能做的事,是两套完全不同的应对机制。

1.2 协调层高可用与数据层高可用是两套独立机制

协调节点主备的逻辑比较接近传统主从:主协调节点持续把系统表里的元数据变更写入WAL,备协调节点通过流复制实时接收并回放。主协调节点宕机或者主动切换时,备协调节点被提升为新的主协调节点,客户端重新连上来就能继续使用。

数据节点的高可玩法则不一样。每个Segment都有自己的主副本(Primary)和镜像副本(Mirror),写入事务提交之前,WAL必须先送达镜像,保证镜像至少不落后于主副本。一旦主副本所在进程故障,会有故障检测服务发现这个情况,然后把对应的镜像激活为新的主副本,同时更新整个集群的路由信息。

这两套机制虽然是设计在同一套MPP里的,但边界必须分清:协调节点挂了,数据节点上的查询工作并不会自动转移到备协调节点,需要提升动作;数据节点挂了,协调节点上的SQL路由会自动避开故障分片,但前提是镜像已经接管。所以配置主备的时候,我的建议是先脑内分清两件事:谁是入口的备,谁是数据的备,然后分别去配置,分别去验证。

2. 搭建前必须做好的规划:服务器、目录、参数一个都不能少

2.1 拓扑与机型建议

MPP主备搭建失败,一半原因是前期拓扑没想清楚就开始动手。这里给一个推荐的基础拓扑:4台物理机,1台协调节点,1台备协调节点,2台数据节点机,每台数据节点机上跑2个Segment实例,每个Segment带一个镜像。

主机集群角色说明
node1协调节点(主)SQL入口,不存业务数据,元数据主副本所在
node2备协调节点 + 数据节点元数据备副本;本机Segment主副本
node3数据节点Segment主副本/镜像副本按规划分布
node4数据节点Segment主副本/镜像副本按规划分布

如果只有3台机器,也可以摆:node1跑协调节点,node2跑备协调节点兼数据节点,node3跑数据节点。但必须记住红线的分布原则:同一个Segment的主副本和镜像副本,绝对不能在同一个物理主机上。镜像的意义就在于主机级故障兜底,主备同机等于没做。

机型上不需要每台都堆顶配。协调节点负责解析SQL和维护元数据,CPU主频和内存带宽更重要,磁盘反而不用特别大,个人建议用SSD就够了。数据节点才是算力主战场,CPU核心数、内存大小、磁盘吞吐都要重点投入。备协调节点日常只做WAL回放和可选只读查询,可以和某个数据节点混布,但生产环境如果预算允许,单独一台会更利于切换后的性能隔离。

2.2 磁盘与目录规划

这里有个非常容易被忽略的细节:数据库高可用最怕的不是硬件坏,而是“磁盘满导致WAL堆积,接着复制中断,最后全集群进入不可用状态”的连锁反应。所以磁盘规划从一开始就要把三类数据分开放:

  • 数据目录:放协调节点元数据、Segment主副本和镜像副本数据。
  • WAL目录:放在线WAL日志,尽量和数据目录不在同一块物理盘。
  • 归档目录:放归档WAL,作为复制链路断裂后的最后兜底。

我的推荐目录结构如下:

/data/mpp/coordinator # 协调节点data目录 /data/mpp/standby # 备协调节点data目录 /data/mpp/primary # 数据节点主副本目录 /data/mpp/mirror # 数据节点镜像副本目录 /data/mpp/wal # WAL在线目录 /data/mpp/archive # WAL归档目录

每个Segment的primary和mirror目录要有独立挂载点,不要图省事所有目录堆在一个大分区里。空间预算上,镜像副本要做全量同步再追增量,所以mirror磁盘剩余空间至少要到当前数据量的2倍才稳妥;WAL目录至少留出20%的总空间余量。很多集群的第一次事故,都是镜像同步跑到一半发现磁盘不够,结果主副本和镜像副本一起卡死。

目录权限必须交给专用数据库账号,700权限是底线。不要用root初始化数据库实例,否则后续所有数据文件权限都会是root,服务进程没法正常读写。

2.3 协调节点关键参数:每个参数都要能说清为什么

下面这段配置是以PostgreSQL内核MPP的默认参数风格写的,你可以对应到自己的发行版文档里。重点不是照抄,而是理解每一项背后的逻辑。

# 协调节点 postgresql.conf 关键项 wal_level = replica max_wal_senders = 16 max_replication_slots = 16 wal_keep_size = 1GB archive_mode = on archive_command = 'test ! -f /data/mpp/wal/archive/%f && cp %p /data/mpp/wal/archive/%f' replication_timeout = 10s
  • wal_level = replica:流复制的基础开关,同时也是很多在线工具执行的前提。如果配成minimal,备库根本拿不到完整WAL。
  • max_wal_senders:决定最多允许多少个复制连接。MPP里不只有一个备协调节点,还有一堆Segment主副本要给镜像投递WAL,这里的数值必须大于“备协调节点数量+正在同步的镜像数量”。16是相对保守的起步值。
  • wal_keep_size:主库保留多少WAL给落后的备库追赶。文件数量太多会占磁盘,太少则备库追不上就必须全量重建。建议和归档配合使用,日常一有告警就查复制延迟。
  • archive_mode和archive_command:归档是复制链路的最后一道防线。当备库因为网络故障掉线期间,主库WAL会持续滚动,如果这些WAL没有被归档保留,备库恢复后只能做全量重建。开归档虽然增加一点IO,但换来的是恢复成本大幅下降。

故障探活参数也比较关键。协调节点上会有故障检测服务周期性探测所有Segment,这类参数一般形如:

fts_probe_interval = 60s fts_probe_timeout = 20s

间隔太短,网络稍微抖动就会引发大面积误切换,这是最危险的“假故障真切换”;间隔太长,节点真挂了要等很久才能触发镜像接管,RTO直接被拉高。建议结合你自己的网络监控历史数据来定,默认值如果业务没意见就别乱调。

2.4 数据节点与网络准备

数据节点上的参数也要预先调好,重点是shared_buffers和work_mem。shared_buffers一般设为物理内存的25%左右,再高容易和操作系统页缓存打架;work_mem决定排序和哈希操作能用的内存,MPP每个Segment并行执行查询时,如果给太大,一个复杂查询就能把整机内存打爆,建议起步给64MB,观察慢查询再逐台上调。

网络是整个MPP主备搭建里最容易成为瓶颈的一环。强烈建议规划两个网段:

  • 业务网:客户端到协调节点、协调节点到Segment的路由通路。
  • 备份/心跳网:WAL传输、镜像同步、心跳探测走专用链路。

两个网段物理隔离,避免业务流量打满网卡时,备协调节点因为收不到WAL或者心跳超时被误判。备份网段建议至少万兆起步,MPP主备的写放大比单机主从严重,因为一份写入要变成多次WAL复制。如果未来数据量增长快,这里不值得省。

账号层面,所有节点创建一个统一的系统账号,比如mpp,UID和GID保持一致。配置SSH免密是管理工具远程操作的基础,但不要用root;数据库进程一律用mpp账号跑。防火墙只放行业务网段和备份网段,不要对公网开放。

3. 主备搭建实操:从初始化到状态验证

3.1 初始化集群:把协调节点和Segment一次拉起

正式搭建的第一步是初始化集群,而不是手动一个个去initdb。MPP的初始化工具会读取一个主机清单和segment分布配置,然后逐台机器SSH执行初始化并汇总状态。用通用化的命令写出来大概是:

mpp-init-cluster -c /home/mpp/cluster.conf

cluster.conf的核心配置项大致如下:

COORDINATOR_HOSTNAME=node1 COORDINATOR_DATA_DIRECTORY=/data/mpp/coordinator SEGMENT_HOSTS=node2,node3,node4 PRIMARY_SEGMENTS=2 MIRROR_SEGMENTS=2

这段配置的意思是:协调节点在node1,数据节点分布在node2、node3、node4三台机器上;每台数据节点机上起2个Segment主副本和2个镜像副本。这里MIRROR_SEGMENTS和PRIMARY_SEGMENTS一旦指定,工具会按照自动感知算法决定镜像放到哪台机器,但底层原则我前面说过了:同一分片的主副本和镜像绝对不会落在同一台物理机。

初始化完成后,第一件事不是急着配备协调节点,而是先确认所有Segment都处于正常服务状态。用集群管理工具查看:

mpp-cluster status --detail

正常输出里应该看到:所有Segment的primary是up,mirror是up。只要有一个镜像状态异常,后续所有工作都建立在不可靠的底座上,建议先排查再继续。

3.2 配置备份协调节点:基础备份 + 流复制

备协调节点推荐用两种方式:一种是用集群管理工具自动添加,类似:

mpp-add-standby-coordinator

另一种是手工方式,原理更直观:基于基础备份把主协调节点的数据目录整体复制到备机,然后启动流复制进程追WAL。即便工具方式自动化程度高,你也应该理解手工方式的每一步,因为排障时会用上。

手工方式的简化步骤:

  1. 在备机上创建主协调节点的同构目录,比如/data/mpp/standby,属主设为mpp账号,700权限。
  2. 执行基础备份命令,把主协调节点数据目录拉到备机:
pg_basebackup -h node1 -p 5432 -U replicator -D /data/mpp/standby -Fp -P -R

-R参数会自动生成standby.signal文件和连接主库的复制配置,这样备机启动后会自动进入恢复模式并开始接收WAL。

  1. 编辑备机上的postgresql.conf,端口建议保持和主协调节点一致。如果端口不同,应用切换后需要修改连接串,这让切换变复杂,生产环境强烈不建议。
  2. 启动备协调节点,观察进程日志,确认状态进入了streaming。

验证复制状态,在主协调节点上执行:

SELECT * FROM pg_stat_replication;

关键看state是否为streaming,以及replay_lag的数值是否稳定在可接受范围。刚初始化完处于追赶状态是正常的,持续一段时间还没追上,就要检查网络和WAL保留量。

3.3 为数据节点配置镜像副本

如果初始化时已经带了MIRROR_SEGMENTS,这一步可以跳过。但很多环境是历史集群先跑了一段时间,才决定补配主备,这时需要在线添加镜像。

添加镜像的操作要在业务低峰期做,因为系统会为每个Segment做一次全量同步,相当于把整个数据库的数据重新拷贝一遍。命令大概是:

mpp-add-mirror --config /home/mpp/mirror.conf

同步过程可以在集群状态里看到:镜像的status从not synchronized变为synchronized。在完全同步之前,这个分片的故障切换能力是不完整的,因此期间不要做任何主备切换演练。

有一点要特别强调:镜像同步完成不等于高可用能力已经生效,还要确认“自动故障切换开关”处于打开状态。不同MPP发行版叫法不同,有的通过系统参数控制,有的通过管理工具控制。打开之后,对Coordinator和Segment之间的心跳探测再做一次确认,再往下走。

3.4 上线前的状态验证清单

直观地排一下最终验收清单,每一项都要看到结果:

  1. 协调节点角色正确:主协调节点active,备协调节点standby。
  2. 所有Segment的primary和mirror状态均为up,且mirror处于synchronized状态。
  3. 备协调节点复制延迟为0,或者在一个极小的持续波动范围内。
  4. 在备协调节点上执行只读查询,能正常返回,确认数据和主协调节点元数据一致。
  5. 用工具跑一次全集群检查,比如mpp-cluster status --detail输出的各节点角色与设计拓扑一致。

最后一条看着简单,但对排查尤其有用。我见过不少环境,配置文件和实际节点角色早就漂移了,靠人肉记忆根本发现不了,跑一次status对照原始规划就能暴露问题。

4. 主备故障切换与恢复:把演练当上线前的必答题

4.1 计划内切换:流程要做成肌肉记忆

主备搭建完,第一场演练应该是计划内切换。计划内切换目的不是测试“坏了能不能顶”,而是验证整套切换流程是不是顺畅、切换之后应用侧是否还认这个环境。

计划内切换的动作没有太多玄学,核心步骤如下:

  1. 提前通知业务方,约定低峰窗口。
  2. 停止业务写入,等待所有事务提交完毕。
  3. 执行协调节点切换操作,这类操作通常都有专门的工命令,比如mpp-coordinator-switchover。
  4. 确认新协调节点可以正常提供服务,检查Segment的自动路由是否正常。
  5. 把应用的连接串切到新协调节点,恢复业务。

这里要提醒一个容易栽跟头的地方:很多应用连接池里缓存了旧协调节点的地址,切完之后看起来业务起来了,但过一会儿连接池里老连接还在,导致新请求不定时失败。建议演练时把连接池的重连机制一起测了,或者在切换后主动触发一次应用端的连接池清理。

4.2 计划外切换:不kill一次,永远不知道系统够不够硬

相比计划内切换,我更建议你在生产上线前做一次模拟计划外故障:直接把主协调节点进程kill -9,或者更狠一点直接关机一台节点。目的有两个:一是测算真实的RTO,二是在无预警状态下检验自动切换链路是否被某些隐性条件卡住。

自动切换发生的过程大致分三步:

  • 故障检测服务发现主协调节点失联。
  • 备协调节点触发提升,开始回放剩余WAL并转为ACTIVE。
  • 新的协调节点接管FTS服务,Segment的primary/mirror如果有故障会被自动调整。

从经验看,最容易出问题的环节是第二步。备协调节点提升时,如果WAL还没完全回放到最新,会出现一小段只读窗口。如果这时候应用持续写入,会拿到连接被拒绝或者只读事务的错误,属于正常现象,但RTO统计要把这部分算进去。

切换完成后,记录三组数字:故障发生时间、新协调节点可服务时间、应用重连完成时间。如果RTO超过业务容忍阈值,先查故障检测周期是否过长,再查备协调节点回放是否形成了瓶颈。

4.3 防止脑裂:宁可少服务,不要双主

MPP主备搭建里,最需要敬畏的一点是脑裂风险。所谓脑裂,就是协调节点和备协调节点之间的网络被切断了,两边都以为自己是唯一的活主,于是同时对外提供服务,元数据开始分叉,等网络恢复后两个节点的数据根本无法合并。

技术上的防线通常有几类:

  • 外部仲裁:引入一个独立的第三方仲裁节点,主备双方在提升前都必须先征求仲裁同意。
  • 心跳隔离(fencing):备机在提升前先通过管理口确认主协调节点已经失联且无法对外服务。比如确认主机的管理口IP已经不通。
  • 多数派原则:当集群超过两台节点时,要求“超过半数的节点认可”才能成为主。

我个人的建议是:不要过分相信任何单一机制,至少把“外部仲裁 + 备机提升前的状态确认”组合在一起。更重要的是,模拟主备之间的网络分区是你上线前必须做的测试之一。只测“主挂了备顶上”不测“两边互相看不见”,高可用体系还是不合格的。

4.4 切换后的数据一致性验证:业务恢复前必做

切换完成后,不要急着把业务放进来。先做一轮数据一致性验证。

  • 检查全局事务ID的连续性,确认回放过程中没有丢事务。
  • 对关键业务表做行数核对和聚合值对比,如果系统里存有切换前的基线快照,把关键表的count(*)和sum(关键字段)与快照对比。
  • 如果产品提供数据校验工具,跑一次全库checksum扫描是更稳妥的做法。

下面这段SQL示意的是最基础的行数核对思路,对应到你的业务表上即可:

SELECT count(*) FROM key_table GROUP BY date_trunc('hour', created_at) ORDER BY 1 DESC;

因为MPP会把一张表的数据分散在多个Segment上,count(*)结果是由所有Segment并行计算后汇总的,这时候拿到的是全局精确值。如果这个结果和预期一致,且关键表没有出现缺分片报错,那数据层面基本可以放心。

有一点要强调:一致性验证必须在“业务写回放开始之前”完成。一旦业务恢复写入,所有后续检查都会混入新数据,那时就很难说清楚某个差异是切换造成的还是新写入产生的。

4.5 故障机重新加入:别指望“一键恢复”

故障切换完成之后,原来的主节点不能直接改回主角色继续用。旧的协调节点在故障前可能还有一些WAL没有发送给备机,直接启动会造成元数据分叉。安全的做法是把旧的主协调节点节点当作一个全新的备协调节点来重建,也就是重新走一遍基础备份加流复制的流程。

Segment的primary故障后,镜像会被提升为新的primary。等旧主机恢复,需要把旧的primary数据目录清空,然后从当前primary重新做全量同步,等状态变成synchronized之后再重新开启自动切换能力。

这里我踩过的坑是图省事,把旧primary直接启动,想让它自动追日志。结果由于旧数据目录里的WAL和当前primary不一致,状态一直停留在异常卡死,最后还是要清空重建,白白浪费时间。记住一条规则:故障恢复阶段,任何角色转换都建议走“清空-重建-重新同步”的路子,不要赌日志追得回来。

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

5.1 问题速查表

故障现象可能原因排查命令/动作
备协调节点同步延迟持续增大备份网带宽不足、WAL堆积查看复制状态里的replay_lag;检查备份网流量;必要时候发起全量重建替代持续追赶
流复制中断WAL文件被清理,备库追赶不上查看pg_wal里文件序号;归档里能不能找到缺失文件;如果追不上,直接全量重建
Segment镜像显示out of sync镜像进程异常退出、网络中断查看数据节点日志;启动镜像进程;触发重同步
切换后新协调节点无法启动数据目录权限异常、端口冲突检查目录属主和700权限;确认postgresql.conf里port是否被占用
故障检测频繁误报探活间隔太短、心跳网抖动调大探活间隔;检查备份网交换机日志;给心跳网做独立VLAN
数据节点磁盘满WAL未及时清理、归档失效查看归档目录;临时清理过期归档;扩容数据盘;恢复到正常后调好清理策略

5.2 复制延迟持续的排查实录

有一次集群里备协调节点的同步延迟一直在涨,从20秒一路涨到20分钟。表面看是网络慢,但备份网当时根本没有大流量。后来查了主协调节点上的WAL目录,发现wal_keep_size配得过小,备库短时间内没法追平,而归档命令又因为归档目录所在磁盘空间不足而静默失败。

根因链条是这样:同步延迟增大 -> 主库WAL滚动过快 -> 保留的WAL不够备库追 -> 归档也失败导致没有其他来源补WAL -> 备库落后越来越多。最后没有继续等,直接停止了备协调节点服务,重新做了基础备份,再恢复流复制,延迟归零。由此得到的经验是:复制延迟一旦出现持续增长,不要盲目等,优先判断能否追赶;如果不能,重做基础备份往往是最快解法。

5.3 FTS误切风险的处置建议

故障检测频率如果设置得太激进,在网络抖动时会发生“假故障真切换”。切换本身是自动的,但如果是误判,就会造成一次完全不必要的业务中断。

应对策略有一事一定要做:资产梳理。把所有节点的主机IP、角色、端口、数据目录、系统账号、防火墙白名单整理成一份资源清单,故障恢复时拿着清单对比现网状态,能节省大量定位时间。

6. 几条值得写进巡检手册的经验

主备搭建完成只是起点,后续日常巡检才是真正拉开水平差距的地方。我个人的习惯是,给MPP集群监控面板加两个最有效的指标:一个是复制延迟曲线,一个是Segment状态变化事件。复制延迟曲线能看到备协调节点和各个镜像副本的健康走势;Segment状态变化事件能在第一时间捕捉到“哪个分片切换过”,避免故障发生很久之后才发现。

关于备协调节点能否承担只读查询,不同MPP发行版的策略不一样。有的支持,有的不支持或支持但受限。如果业务想用备协调节点的只读能力分摊压力,一定要先确认版本支持度,再实测复杂查询的表现。备协调节点的本职工作是在主节点故障时顶上去,如果平时被重度查询拖垮,到了真正需要提升的时候反而可能因为资源不足而提升失败。

演练记录建议保留完整的历史。每次计划内切换、计划外演练,把步骤、耗时、遇到的问题、改动过的配置都写下来。下一次做HA变更的时候,直接翻上一次的记录会省很多时间。

最后分享一个小技巧:当主备切换后原主节点需要重新加入,操作之前先把当前集群状态和配置清单导出一份。如果重建过程出了差错,靠着这份基线还能快速回滚;如果一切顺利,这份结构也能作为下一次故障恢复的对照基准。就这套思路,能让主备维护从“凭感觉”变成“有章法”。

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

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

立即咨询