
1. 为什么边缘场景需要一套“不贵”的高可用方案先聊个背景。我在生产环境里接触过不少物联网边缘项目它们的数据库部署形态和互联网机房里的典型架构差别非常大。边缘机房通常只有几个节点网络条件没有数据中心那么可靠带宽也有限很多时候还只有一个机柜的物理空间。在这种条件下指望标准的三节点甚至五节点分布式数据库集群并不现实资源浪费太大运维成本也扛不住。但边缘业务对数据连续性的要求一点不比中心机房低——生产线的SCADA系统、园区能源管理平台、智慧水务的采集网关任何一端的数据库宕机直接意味着采集链路中断、历史数据出现空洞严重的还会影响控制回路。所以双节点高可用在边缘场景是刚需。但双节点方案有个绕不开的难题怎么保证两个节点上的数据是一致的同时故障切换的时候又不丢数据、不产生脑裂。我这次要分享的方案组合是KaiwuDB DRBD Pacemaker。KaiwuDB 是一款面向工业物联网、能源物联网场景的分布式时序数据库支持 SQL具备时序数据压缩、级联采集、边云协同这些能力单机版在边缘侧部署非常轻量。DRBD 负责在块设备层面对数据库的数据目录做实时镜像复制Pacemaker 负责资源管理和故障切换。这套组合在边缘场景里跑下来整体表现是稳的而且成本很低——两台 x86 服务器加一张网卡就能起步相比存储阵列或者全分布式数据库投入不是一个量级。文章会分成几个部分先讲清楚这套方案的架构思路和技术选型逻辑然后把 DRBD、Pacemaker、KaiwuDB 三者之间如何衔接讲透接着给出完整的部署步骤和配置内容再分享故障切换的实测结果和我在真实环境里遇到过的坑。如果你也在做边缘侧数据库的高可用设计这篇文章可以直接当作业抄。2. 整体架构设计思路与技术选型2.1 双节点高可用在边缘场景的特殊性在设计这套方案之前我先把边缘场景对高可用方案的约束条件列出来。边缘机房对成本和空间极度敏感所以第一约束是节点数量不能多两台是上限第二约束是硬件不能太特殊不能用 FC 存储交换机这类专用设备因为现场没有这个条件第三约束是网络不能假设太好边缘机房到中心机房的链路经常不稳定但两个节点之间的内网链路倒是可控的可以走千兆甚至万兆。基于这些约束双节点高可用的核心思路就清晰了数据层面必须保证两个节点的本地数据尽量实时一致这样任意一个节点宕机另外一个节点可以立即接管应用层面需要有一个集群管理器来监控资源状态、决定节点角色、在故障时触发切换同时要防止两个节点同时认为自己是主节点。这里我先解释一个很多人容易混淆的点双节点高可用不等于集群数据库。KaiwuDB 本身是支持分布式部署的但在边缘场景里我更倾向于先用单机模式部署再在操作系统层面用 DRBD 和 Pacemaker 把两台机器“粘”成一个高可用对外整体。为什么这么做因为分布式模式对节点间网络稳定性要求更高边缘机房如果两个节点之间的心跳网络出现闪断分布式数据库内部的选举和同步机制会产生大量的重试和告警反而增加了运维负担。而 DRBD Pacemaker 是操作系统层面的成熟方案故障域更小行为更可控切换时间也更短——实测下来秒级切换完全做得到。2.2 为什么要选 DRBD 而不是分布式存储或主从复制在数据库高可用方案里数据同步有几种主流选择数据库自带的复制功能、分布式存储比如 Ceph、块设备层面的实时镜像。我逐个说一下为什么最终选了 DRBD。数据库自带复制比如 MySQL 的半同步复制、PostgreSQL 的流复制确实可以做到数据库层面的副本一致。但问题是这种方式和具体数据库的版本、配置、运维经验强绑定。KaiwuDB 本身包含多个数据组件、元数据组件和时序引擎组件如果要在数据库层面梳理清楚主备之间的数据流向我需要逐一确认引擎内部的数据落盘方式复杂度完全不亚于写一套新的复制逻辑。而且边缘现场的运维人员你让他去理解数据库内部的复制机制远不如让他理解“两个硬盘内容一模一样”来得直观。分布式存储的问题更直接——重。部署 Ceph 至少要三台 mon 节点、一组 OSD配置和管理复杂度在边缘场景完全是负担。而且 Ceph 自带网络内复制本来就是为了云平台这种大规模虚拟化场景设计的在双节点场景下属于杀鸡用牛刀延迟还高。DRBD 的本质是 Linux 内核里的一个块设备驱动它把两台机器上的裸设备、分区或者 LVM 逻辑卷做镜像同步。应用程序写入主节点 DRBD 设备的每一个数据块都会同时复制到备节点的对应设备上。对于数据库进程来说它根本感知不到自己在往一块“被镜像”的磁盘上写数据进程看到的只是一块普通的块设备。这样带来的最大好处是无论 KaiwuDB 内部有多少种数据文件、WAL 文件、元数据文件只要它们都落在 DRBD 设备上数据的实时一致性就由 DRBD 保证了不需要我去关心 KaiwuDB 内部每个文件什么时候落盘、怎么同步。2.3 Pacemaker 在角色协商中承担的职责DRBD 解决了数据一致性的问题但还没有解决“主备角色由谁来定”的问题。两个节点上的 DRBD 设备都需要能被挂载但同一时刻只有主节点允许挂载和读写主节点如果宕机需要有一个机制让备节点自动提升为主节点并挂载文件系统再拉起 KaiwuDB 服务。这个协调和决策的工作交给 Pacemaker。Pacemaker 是一个集群资源管理器它和 Corosync 这个底层通信组件配合工作。Corosync 负责在两个节点之间传递心跳消息和集群成员信息Pacemaker 则是基于这些信息做出决策——谁在集群里、谁失联了、某个资源当前应该运行在哪台节点上。Pacemaker 的资源管理模型里这些资源可以是 IP 地址、文件系统挂载点、LVM 逻辑卷也可以是 systemd 服务还可以是一个简单的 shell 脚本。我要做的就是把 DRBD 设备、LVM 卷、文件系统挂载、KaiwuDB 服务这四类资源统统交给 Pacemaker 管理并配置好它们之间的启动顺序和共置约束。整个架构跑起来之后数据流的走向是这样的KaiwuDB 进程写入数据到挂载点下的文件落盘到 LVM 逻辑卷逻辑卷底层是 DRBD 设备DRBD 内核模块把数据块同步到备机的 DRBD 设备上。备机虽然不挂载文件系统但它的 DRBD 设备上已经存在了和主节点完全相同的数据块。一旦主节点故障Pacemaker 在备机上依次完成 DRBD 提升、逻辑卷激活、文件系统挂载、KaiwuDB 服务启动这几步同时把 VIP 漂移到备机客户端连接使用相同的 IP完全无感知。2.4 这套方案的优势与边界条件这套方案的优势总结下来有四点。第一是硬件要求低两台普通服务器加两块千兆网卡就能跑不需要共享存储第二是切换对应用透明KaiwuDB 进程层面无感知数据零丢失第三是运维模型简单数据一致性由 DRBD 保证、资源调度由 Pacemaker 保证不需要额外开发脚本第四是在工业物联网场景里客户对 Linux 下的 DRBD 和 Pacemaker 普遍有认识审计和验收时容易讲清楚。但边界条件也要说清楚。这套方案保护的是“服务器宕机、数据库进程异常、操作系统崩溃”这类节点级故障不保护“数据文件被误删除”这类逻辑错误——如果有人在主节点上执行了删除命令这个删除动作会被 DRBD 同步到备节点两边的数据都会受影响。所以这类方案必须搭配定期备份和监控告警。另外双节点方案里的脑裂问题需要刻意防护具体怎么做我放在后面单独讲。3. 核心组件原理拆解3.1 DRBD 的同步机制详解DRBD 的原理可以类比成“网卡级别的 RAID-1”。RAID-1 是把一个数据块同时写到同一台机器里的两块硬盘上DRBD 则是把数据块写到两台不同机器的本地盘上。为了实现这个能力DRBD 在内核里注册了一个新的块设备驱动你会在 /dev 下看到 drbd 设备比如 /dev/drbd0。上层文件系统对这个设备做读写时DRBD 驱动会在本地执行 I/O 的同时把同样的写请求通过 TCP 连接发送到对端节点对端节点的 DRBD 驱动把数据写到它自己的本地存储上。DRBD 有两种核心工作模式同步和异步。异步模式下主节点本地写盘成功后立即返回应用写入成功数据块在后台发送到备机所以主备之间可能有短暂的数据不一致窗口同步模式下主节点要等备机确认数据已经写入成功之后才向应用层返回写成功因此两边的数据始终一致代价是写延迟会叠加一次内网网络往返的时间。边缘场景采集数据的特点是持续写入但单次写入量不是特别大而且我们要保证故障切换时不丢数据所以必须采用同步模式。DRBD 把复制协议的等级分成了 A、B、C 三档。协议 A 是异步模式协议 B 是半同步协议 C 是同步模式。我用的就是协议 C。内网延迟在 0.1ms 级别的条件下协议 C 带来的额外写延迟几乎可以忽略。另一个需要理解的概念是 DRBD 的三种资源角色Primary、Secondary、Primary 的退化状态。主节点上的 DRBD 资源处于 Primary 状态可以挂载文件系统并对外提供读写备节点上的 DRBD 资源处于 Secondary 状态不可挂载它只是默默地接收主节点传来的数据块。当主节点故障时备节点的 DRBD 资源需要从 Secondary 提升为 Primary。DRBD 支持两种提权方式手动提权和自动提权。自动提权依赖 DRBD 的断开/连接策略和 quorum 概念具体行为由配置参数控制。在 Pacemaker 环境中更常见的做法是不把 DRBD 的自动提权功能当作第一依赖而是由 Pacemaker 在故障切换流程中按顺序执行提权操作。这样的好处是切换流程的所有步骤都能被 Pacemaker 感知、记录和审计。3.2 Pacemaker 的资源管理模型Pacemaker 的基本操作单位叫做资源resource一个资源可以是一个 IP 别名、一个文件系统挂载项、一个 LVM 逻辑卷、一个 systemd 服务等。资源之间通过约束constraint建立关系约束分为三种顺序约束决定资源启动的先后次序共置约束决定资源必须运行在同一个节点上位置约束决定资源在正常情况下倾向于在哪个节点运行。这套方案里我需要定义这些资源DRBD 资源名字可以叫 kaiwu_drbd类型为 ocf:linbit:drbd作用是让 DRBD 设备在线、资源对连接LVM 资源名字叫 kaiwu_lvm类型为 ocf:heartbeat:LVM作用是在节点上激活卷组文件系统资源名字叫 kaiwu_fs类型为 ocf:heartbeat:Filesystem作用是把逻辑卷挂载到 /data/kaiwu 目录IP 资源名字叫 kaiwu_vip类型为 ocf:heartbeat:IPaddr2作用是绑定 VIP 到当前主节点的网卡上服务资源名字叫 kaiwu_service类型为 systemd:kaiwu作用是启动和停止 KaiwuDB 的系统服务约束配置上我会把所有资源做成一个资源组group组内的资源强制要求按顺序启动、全部同节点运行。资源组的定义方式是把多个资源放进同一个 group 里Pacemaker 自动为它们建立顺序和共置关系。这比手动写多条约束要简单得多而且在后面的故障排查里更容易看清依赖关系。Pacemaker 有一个和双节点场景强相关的概念叫 fence隔离、仲裁。在双节点集群中如果两个节点之间的心跳联系中断了两个节点都会怀疑对方已经死了这时候如果没有一个“裁判”来阻止双方都去抢占资源就会出现两个节点同时以 Primary 状态挂载 DRBD 设备、同时启动 KaiwuDB 服务的情况——这就是脑裂。在双节点场景里脑裂最危险的部分不在于 DRBD 两边数据不一致而在于两个数据库进程同时对外提供写入服务会彻底破坏数据一致性。Pacemaker 的典型做法是配置 fence 设备在确认节点失联后强制把对方节点的电源关掉或者去激活对方的共享存储。但边缘场景没有 IPMI 带外管理的情况很常见所以还有一种折中方案是配置 SBD 存储隔离利用共享块设备上的仲裁区来做决策。不过即使没有带外管理DRBD 本身也提供了一种 fencing 机制——fence-peer 和 unfence-peer配合 Pacemaker 的 stonith 可以让失联节点上的 DRBD 资源自动退化这个概念在下面的部署里会具体出现。3.3 KaiwuDB 在这套架构中的角色与数据落盘路径KaiwuDB 作为数据库层在这套方案里不需要感知集群的存在它就是一个单机数据库实例。需要关心的是它的数据文件存储在哪里以及它怎么和文件系统打交道。KaiwuDB 的数据目录包括数据文件、WAL 预写日志、临时文件和配置文件。我在部署的时候把整个数据目录都放在 DRBD 设备上。数据库进程启动时读写数据文件的路径完全落在 DRBD 块设备映射的文件系统上所以 KaiwuDB 本身不需要做任何高可用相关的配置它的所有数据变更都会在块设备层被 DRBD 复制到备机。这里有一个关键点KaiwuDB 在启动时会检查数据目录的状态包括 WAL 是否存在、数据文件是否完整。如果主节点故障时某些数据还没有来得及由数据库进程自己刷盘但这些数据可能已经被 DRBD 同步到备机了因为 DRBD 工作在块设备层它复制的是所有写入块设备的数据块比数据库层面的事务提交状态更底层。结果就是即使数据库进程崩溃了只要 DRBD 已经同步了对应的块备机接管后依然能拿到这些数据。但要提醒的是DRBD 同步的是块设备写操作不保证上层文件系统事务的完整性。如果主节点在写入文件系统元数据的过程中突然断电DRBD 上备机拿到的块副本可能对应的是一个中间状态的文件系统。所以在故障切换流程里一定要做文件系统日志的重建。我们的环境里用的是 ext4 文件系统在挂载时它能够自动回放日志所以实际切换后不会有文件系统层面的损坏问题。更好的选择是 xfs它在意外掉电后的恢复能力也很强。我在生产环境里用的是 xfs这个选择在后文的部署章节会体现。4. 环境规划与完整部署实录4.1 节点与网络规划我先列出实验和生产共用的部署环境信息。两个节点的主机名和 IP 规划如下节点主机名管理 IPDRBD 专用 IP角色节点1kaiwu-node1192.168.100.1110.10.10.1初始主节点节点2kaiwu-node2192.168.100.1210.10.10.2初始备节点VIPkaiwu-vip192.168.100.20-对外服务 IP管理 IP 用于集群通信、SSH 和客户端访问DRBD 专用 IP 用于数据同步流量建议走独立的物理网卡或者至少独立 VLAN避免和管理流量互相抢占带宽。我这里两台机器都是双网卡一条千兆内网走管理一条万兆走 DRBD 同步数据同步延迟实测下来非常低。存储规划上我在每台机器上准备了一块独立的 SSD 作为 DRBD 底层存储不需要做 RAID因为 DRBD 本身就是最底层的冗余。整个磁盘划分如下/dev/sda系统盘安装操作系统/dev/sdbDRBD 底层盘后续做 LVM 卷组在这上面创建逻辑卷给 KaiwuDB 用两个节点上的底层盘大小和型号最好一致DRBD 同步的速度和容量匹配度会好很多。如果两块盘容量不一致DRBD 按较小容量创建资源剩下的空间浪费这一点规划硬件的时候就要注意。4.2 操作系统与基础依赖我的两个节点都是 CentOS 7.9 或者兼容的 Linux 发行版。需要先做几个基础调整关闭防火墙或者放行指定端口禁用 SELinux或者配置好 SELinux 策略配置好主机名解析让两个节点能通过主机名互相访问。DRBD 和 Pacemaker 的安装包在 EPEL 源和高可用源里都有。CentOS 7 的安装命令大概是yum install -y epel-release yum install -y drbd84-utils kmod-drbd84 yum install -y pacemaker pcs corosync fence-agents-all以 DRBD 8.4 为例加载内核模块后确认一下模块是否存在modprobe drbd lsmod | grep drbd对 Ubuntu/Debian 系的系统命令类似apt install -y drbd-utils pacemaker pcs corosyncCentOS 7 里 pcs 是最常用的集群管理工具它的作用是提供命令行接口来配置 Corosync 和 Pacemaker。KaiwuDB 所在的服务器需要安装的依赖很少主要是 glibc、libnuma 这些基础库官方文档里有详细清单按照文档装好即可。4.3 DRBD 资源配置与初始化我先规划好名字DRBD 资源名就叫 r0对应的块设备是 /dev/drbd0。配置文件在 /etc/drbd.d/ 目录下先写入全局配置再写入资源定义。/etc/drbd.d/global_common.conf 里的核心设置global { usage-count no; } common { protocol C; disk { fencing resource-only; } net { cram-hmac-alg sha1; shared-secret kaiwu-edge-hA; after-c 0; max-buffers 8192; max-epoch-size 2048; sndbuf-size 1024k; rcvbuf-size 1024k; } syncer { rate 200M; verify-alg crc32c; } }几个关键参数解释一下。protocol C 就是前面说的同步复制协议。cram-hmac-alg 配置的是 DRBD 节点之间认证算法shared-secret 就相当于两个节点约定的口令。syncer rate 是数据同步时的带宽上限这里给 200M 是为了避免同步流量把网卡打满如果底层盘很大可以适当调高。资源定义文件 /etc/drbd.d/r0.resresource r0 { on kaiwu-node1 { device /dev/drbd0; disk /dev/sdb; address 10.10.10.1:7788; meta-disk internal; } on kaiwu-node2 { device /dev/drbd0; disk /dev/sdb; address 10.10.10.2:7788; meta-disk internal; } }这里的 address 是 DRBD 专用 IP 和端口号两个节点要对端配对。meta-disk internal 表示 DRBD 的元数据放在磁盘内部不需要单独划一个分区。两个节点都配置完成后先初始化元数据再启动资源drbdadm create-md r0 systemctl start drbd drbdadm up r0初始化完元数据后把节点1的设备设为 Primary 并创建文件系统drbdadm primary r0 --force mkfs.xfs /dev/drbd0 mkdir -p /data/kaiwu mount /dev/drbd0 /data/kaiwu这一步执行完节点1上的 /dev/drbd0 已经是可读写的 xfs 文件系统了。另一个节点此刻应该能看到同步状态可以通过 cat /proc/drbd 或者 drbdadm status r0 查看同步进度。4.4 LVM 逻辑卷与 KaiwuDB 数据目录绑定DRBD 设备可以直接在上面创建文件系统使用但我建议还是叠加一层 LVM。原因有两个一是后续如果需要扩容用逻辑卷比直接对整块磁盘做 mkfs 要方便二是 KaiwuDB 的数据目录和日志目录可以分开挂载便于做独立的 I/O 限制和监控。在 Primary 节点上创建 LVM 逻辑卷卷组名字我叫 vg_kaiwu逻辑卷名字叫 lv_kaiwupvcreate /dev/drbd0 vgcreate vg_kaiwu /dev/drbd0 lvcreate -L 800G -n lv_kaiwu vg_kaiwu mkfs.xfs /dev/vg_kaiwu/lv_kaiwu注意LVM 的物理卷元数据也需要被 DRBD 同步而 DRBD 只支持一层所以在两个节点上的 LVM 操作只需要在某个时刻执行一次。所有节点上都会看到相同的 PV/VG/LV 信息因为块的复制是整盘粒度的LVM 元数据也在被复制的范围内。创建好逻辑卷后在 /data/kaiwu 目录下挂载逻辑卷mount /dev/vg_kaiwu/lv_kaiwu /data/kaiwu然后下载并解压 KaiwuDB 的安装包把数据目录初始化到 /data/kaiwu 下。KaiwuDB 的部署方法官方有文档核心步骤是创建 kaiwu 用户、把安装目录和数据目录属主改成 kaiwu、按照模板配置 kaiwu.conf 文件里的存储路径指向 /data/kaiwu。之后用 systemd 管理 KaiwuDB 服务cp kaiwu.service /etc/systemd/system/ systemctl daemon-reload systemctl start kaiwu为了确认 KaiwuDB 真的把数据写到 DRBD 设备了可以用 blkid 和 df 验证挂载路径也可以通过写入一条测试数据后在备机上查看 DRBD 底层盘的数据变化。实测中我直接在 KaiwuDB 里建表插入数据备机的 /proc/drbd 里可以看到主备之间的数据包计数在增长就说明同步链路完整。4.5 Pacemaker 集群初始化先配置集群软件本身。pcs 的配置方式在 CentOS 7 里是systemctl start pcsd systemctl enable pcsd passwd hacluster pcs cluster auth kaiwu-node1 kaiwu-node2 -u hacluster -p yourpassword pcs cluster setup --name kaiwu_cluster kaiwu-node1 kaiwu-node2 pcs cluster start --all pcs cluster enable --all这里用到的 hacluster 用户是 pcs 用来管理集群的系统用户设置好密码之后才能在两个节点之间建立信任。然后确认集群在线状态pcs status正常输出里应该显示两个节点都在线Corosync 通信正常Pacemaker 在运行。接下来才是重头戏——把 Pacemaker 的集群属性调成适合双节点并且适合 DRBD 的模式。因为我用的是 DRBD我对集群做了两个重要设置pcs property set stonith-enabledfalse pcs property set no-quorum-policyignore这两个设置新手看到容易慌。先说明stonith-enabled 设置为 false 是因为我没有配置独立的 fence 设备脑裂的防护交给 DRBD 自己的 couple 机制去处理也就是前面配置里的 fencing resource-only。no-quorum-policyignore 是因为双节点集群在正常情况下只有两票如果按默认 quorum 规则两台需要至少两台存活才有法定票数这样一台宕机集群就完全瘫痪了不符合高可用预期。所以在双节点环境下设置成 ignore 让单节点也能继续运行资源和提供服务。这里有一个坑要提醒关掉 stonith 意味着如果两个节点真脑裂了没有物理手段强制某个节点断电所以一定要保证 DRBD fencing 配置是有效的。我在生产环境里宁可多配置一层 SBD 隔离也不会裸奔但受限于篇幅这套方案里我默认 DRBD 的 fencing 足够应对常见故障场景。4.6 定义集群资源组资源组的定义顺序非常重要前面的资源必须先于后面启动。Pacemaker 资源组里的资源按声明顺序启动按相反顺序停止。所以我的声明顺序就是 DRBD 先、LVM 次之、文件系统第三、VIP 第四、KaiwuDB 服务最后。先创建 DRBD 资源pcs resource create kaiwu_drbd ocf:linbit:drbd drbd_resourcer0 \ promotable clonetrue这里用到了 promotable clone 类型。DRBD 资源在 Pacemaker 里不是一个普通资源它需要支持主备两个角色并且要保证一台节点上是 Primary、另一台上是 Secondary。Pacemaker 管这种资源叫做多状态资源或可升级克隆资源。声明成 promotable clone 后Pacemaker 就自动遵守 DRBD 的主备约束。然后创建 LVM 资源、文件系统资源、VIP 资源和服务资源pcs resource create kaiwu_lvm ocf:heartbeat:LVM \ volgrpnamevg_kaiwu exclusivetrue \ --group kaiwu_group pcs resource create kaiwu_fs ocf:heartbeat:Filesystem \ device/dev/vg_kaiwu/lv_kaiwu directory/data/kaiwu fstypexfs \ --group kaiwu_group pcs resource create kaiwu_vip ocf:heartbeat:IPaddr2 \ ip192.168.100.20 cidr_netmask24 \ --group kaiwu_group pcs resource create kaiwu_service systemd:kaiwu \ op monitor interval30s \ --group kaiwu_group以及把多个资源组成组使用如下方式pcs resource group add kaiwu_group kaiwu_drbd_clone pcs resource group add kaiwu_group kaiwu_lvm pcs resource group add kaiwu_group kaiwu_fs pcs resource group add kaiwu_group kaiwu_vip pcs resource group add kaiwu_group kaiwu_service注意这里有个细节DRBD 资源是一个 promotable clone它作为一个整体被放进资源组但组内启动顺序是 DRBD 的逻辑先就绪。Pacemaker 会自动等待 DRBD 资源变成 Primary 之后才启动同组内的后置资源。全部定义完成后用pcs resource config看看输出检查每项参数是否和预期相符。pcs status里应该能看到资源当前跑在节点1上VIP 和 KaiwuDB 服务都正常。4.7 KaiwuDB 服务的 systemd 单元编写服务资源使用 systemd:kaiwu 需要在两个节点上都有 /etc/systemd/system/kaiwu.service 文件。这个文件的内容其实很简单主要作用是启动和停止 KaiwuDB 的单机进程。参考模板[Unit] DescriptionKaiwuDB Server Afternetwork.target [Service] Typesimple Userkaiwu Groupkaiwu WorkingDirectory/opt/kaiwu ExecStart/opt/kaiwu/bin/kaiwu start ExecStop/opt/kaiwu/bin/kaiwu stop Restarton-failure LimitNOFILE65536 [Install] WantedBymulti-user.target实际部署时我用的是 KaiwuDB 自带的启停脚本或者 wrapper 命令相关的环境变量在 /etc/default/kaiwu 里配置。这里特别提醒Pacemaker 的 systemd 资源有一个特性它监控服务是否 active如果服务进程自己退出了Pacemaker 会把它当作资源故障触发切换逻辑。所以 systemd 脚本里的 Type 和 ExecStart 参数一定要核对清楚不能写一个一次执行完就退出的命令进去否则 Pacemaker 会误判服务已启动完成。5. 故障切换实操与切换时间实测5.1 手动切换流程演练在实际故障发生之前先做一次干净的手动切换演练把整个集群资源从节点1迁移到节点2确认整条链路是通的。命令如下pcs resource move kaiwu_group kaiwu-node2这个命令会为资源组添加一个位置约束让它强制运行在节点2上。Pacemaker 会自动把资源组逐项停止再在新节点依次启动。迁移完成后用下面的命令清理临时约束否则下一次切换可能还会被上次的约束干扰pcs resource clear kaiwu_group整个干净切换过程我实测控制在 5 到 8 秒之间。其中耗时大头在 KaiwuDB 服务的冷启动KaiwuDB 需要加载 WAL、做恢复检查10 秒以内完成边缘场景完全可以接受。切换完成后可以通过 KaiwuDB 的 SQL 接口连到 VIP 上验证数据完整性。我做的事是提前在库里建一张测试表写入几千行带时间段的数据切换后再做一次 count 和最新时间戳对比确认数据没有丢失。5.2 模拟主节点宕机再来做一个更真实的故障演练直接拔掉节点1的电源。操作完成后观察节点2上的状态变化过程。首先是 Corosync 在一到两秒内感知到节点1失联集群成员发生变化。随后 Pacemaker 判定节点1上的所有资源不可用开始执行资源接管流程。节点2上的 kaiwu_drbd 从 Secondary 提升为 PrimaryLVM 激活逻辑卷文件系统挂载到 /data/kaiwuVIP 漂移到节点2KaiwuDB 服务启动。我在多次测试中记录到的切换时间是 8 到 12 秒比手动切换稍长原因在于 Corosync 需要时间确认节点失联并且 DRBD 的分裂脑检测也需要一个短暂的等待窗口。把这段时间也算上总对外不可用时间在 15 秒以内这个指标对边缘采集场景是够用的——采集端配置了本地缓存的话完全无感。5.3 数据一致性验证方法切换完成后最重要的动作不是看服务起来了而是验证数据一致性。我从三个层面做验证。第一层是块设备层面。切换完成后在节点2上执行drbdadm status r0应该显示该节点是 Primary/UpToDate 状态。如果有 failed 或者 inconsistent 标记说明 DRBD 同步出了问题。第二层是文件系统层面。挂载完成后检查文件系统日志是否干净以及挂载点下的文件总数和切换前做快照时记录的文件数是否一致。xfs 文件系统在这种掉电切换场景下的表现很稳定实测多次没有出现文件丢失。第三层是数据库层面。连上 VIP 执行 SQL 查询统计测试表的数据量和最后写入的时间戳。如果 KaiwuDB 内部有 WAL 恢复日志也一并查看确认没有 panic 和未完成事务。6. 常见问题与排查技巧实录6.1 两个节点同时变成 Primary 的脑裂处理这是双节点高可用里最典型的故障。原因是两个节点之间的心跳断开了而 DRBD 又没有能及时把某个节点的资源降级。出现脑裂后DRBD 会把资源标记为 StandAlone两边都持有最新数据的版本信息。处理办法是按时间先后判断哪边的数据更新保留较新的数据作为主。因为我用的是协议 C 同步复制正常运行时两边数据一致脑裂后旧主节点可能还有少量未同步数据。我的操作步骤是首先不要急于重新连接两个节点先把两边 DRBD 的 sync 状态和数据时间戳记录下来。然后主动把确认数据较旧的那一端降为 Secondary在较新端执行drbdadm connect r0重新建立连接之后观察同步是否完成。清理完后一定记得清理 Pacemaker 里的残留资源状态把资源重新交给集群管理而不是让某一端一直手动持有资源。脑裂发生的根因要查比如心跳网线松动、Corosync 配置错误、防火墙拦截了心跳端口。我遇到过一次是 pcsd 服务挂掉导致集群状态卡住也很容易误判成网络问题。6.2 切换后 KaiwuDB 数据目录权限不对这个问题出现概率很高根因是 KaiwuDB 服务是以 kaiwu 用户运行的但 DRBD 设备挂载出新文件系统后挂载点属主可能是 root。切换完成后 KaiwuDB 服务无法在数据目录下创建文件直接启动失败。解决方式有两种。一种是在挂载后手动 chown 数据目录属主为 kaiwu但这种方式在切换后还得手动处理不够优雅更好的方式是在 systemd 单元里加 ExecStartPost 脚本在服务启动前自动修正属主。实际生产里我在 /etc/systemd/system/kaiwu.service 里加了一行ExecStartPre/bin/chown -R kaiwu:kaiwu /data/kaiwu这样无论资源从哪个节点起来KaiwuDB 都有正确的写权限。6.3 Pacemaker 资源组漂移后无法自动返回原节点默认配置下Pacemaker 在故障切换后不会自动把资源组回切到原节点除非原节点恢复后触发某种位置约束的干预。这个设计其实是故意的避免主备来回摆动造成不必要的服务中断。但在运维中会发现原节点恢复后新主节点上的 DRBD 数据虽然是最新状态原节点重启后 DRBD 需要把新主节点变化的数据同步回去这段时间原节点的 DRBD 状态是 SyncSource 或者 SyncTarget。要回切的话操作顺序是先让同步完成再执行pcs resource move kaiwu_group kaiwu-node1然后清理约束。不能赶在同步完成前回切否则 DRBD 会再次进入不一致状态极端情况下会触发新的脑裂风险。6.4 DRBD 同步长期停留在连接状态应用层进程持续大量写入时偶尔会出现 DRBD 同步速率跟不上写速率的情况表现为同步进度一直上不去甚至停留在 0% 或反复倒退。这是同步复制场景下典型的重负载问题。排查手段是看主节点的 IO 等待和网络吞吐。我遇到过两种真实情况一是底层盘是机械盘IOPS 太低换成 SSD 后问题消失二是 syncer rate 配得比实际网络带宽小太多阻碍了同步进度调大 rate 之后恢复了。生产环境建议底层盘全部上 SSD网络至少保证 DRBD 同步流量独享一条千兆链路没有瓶颈可犯。6.5 切换后 VIP 飘移了但客户端缓存了旧连接边缘场景里很多采集终端用 TCP 长连接连数据库VIP 漂移后旧连接立即断开终端应用如果重试逻辑做得不够好可能长时间连不上新主节点。这虽然不是集群配置的问题但直接影响切换效果。我建议所有边缘接入程序采用连接池加自动重连机制数据库连接串里配置的是 VIP 而不是某个固定 IP。KaiwuDB 的 SQL 客户端重连配置和常见时序库类似设置好超时时间和重试次数实测切换期间只影响当次请求后续自动恢复。6.6 关于脑裂防护的另一层保障前面多次提到脑裂防护我再补充一个更稳妥的实践。如果现场有条件提供一块共享存储的小分区比如几十 MB可以给每台机器挂一个 SBD 设备利用 SBD 作为 fence 机制。Pacemaker 的 stonith 设备类型配置成 fence_sbd配置正确后即使两个节点完全失联SBD 也会用存储锁来决定哪个节点可以继续运行资源。没有共享存储的情况下我退而求其次用 DRBD 自带的 fencing 机制来防止双方同时变 Primary。但我必须强调DRBD fencing 依赖两个节点之间还能通过 DRBD 网络通信来判断对端状态如果心跳和 DRBD 网络同时断掉DRBD fencing 也无力回天。所以物理上至少保持两条独立网络路径一条走管理心跳一条走 DRBD 数据同步是边缘节点部署的硬性要求。我在实际部署的机房环境里遇到两次因为交换机单链路故障导致的管理网络闪断正是因为有独立的 DRBD 数据链路和冗余心跳集群才没有进入脑裂状态。这个冗余设计值得每一套边缘高可用方案默认启用。7. 监控、日常维护与多场景延伸7.1 监控指标体系部署完成不等于可以放任不管。我至少会监控以下几类指标DRBD 状态通过 drbdadm status r0 定时采集重点关注角色是否正常、同步是否完成、连接是否为 ConnectedPacemaker 集群状态pcs status 输出关注是否有资源异常、节点是否离线KaiwuDB 进程状态systemctl status kaiwu关注进程是否存活、WAL 目录大小是否异常磁盘延迟xfs 和底层盘的 iostat 数据异常延迟通常意味着 DRBD 同步或者底层存储有问题网络延迟和丢包管理网和数据网分别监控特别是两张网的 ping 延迟我用的监控方式比较简单写一个 bash 脚本每分钟采集一次状态指标推送到中心机房的看板即可。边缘节点的采集端不会很重不需要部署完整的 Prometheus 全家桶脚本加阈值告警足够用。7.2 维护窗口与常规操作高可用集群虽然自动化程度高但日常维护仍然需要规范。比如给主节点做内核升级我先执行pcs resource move kaiwu_group kaiwu-node2把业务切走确认所有资源都跑在节点2且数据同步完成后再对节点1执行维护。节点1回归集群前要确认 DRBD 同步进程完成业务不切回的话也没有问题保持节点2为主节点即可。升级 KaiwuDB 版本时我会按备机→主机的顺序操作。先在备机上升级软件包但不启动新版服务因为它处于 Secondary 状态不涉及到对外服务。再通过一次切换让备机转正验证新版进程能正常启动、数据完整最后再升级原来的主节点。这种方式可以把升级窗口的对外影响控制在一次切换的时间内。7.3 扩展到其他数据库的场景这套 DRBD Pacemaker 组合并不绑定 KaiwuDB换成 MySQL、PostgreSQL、Redis 这类单机部署的数据库同样适用。实际上我在某些边缘项目里也用过完全相同的架构承载 PostgreSQL 的时序扩展。差异点只在服务资源的 systemd 单元以及数据库本身数据目录的规划。也就是说这套方案是边缘侧数据库高可用的一个通用底层框架数据库是谁不影响架构的正当性。需要注意的场景是数据库本身已经支持多节点分布式模式的比如 KaiwuDB 自身的分布式版本、TiDB、CockroachDB 这类那就不需要再叠加 DRBD 了分布式架构内部自带副本机制。DRBD Pacemaker 最适合的场景是“单机数据库形态 边缘高可用要求”的组合这个定位要搞清楚别堆叠无意义的复杂度。7.4 规划资源容量和备份策略最后两件事提醒一下容量规划和备份。容量规划上DRBD 设备可以后期扩容但操作相对繁琐。最好在一开始就按至少两年业务增量估算逻辑卷大小。边缘采集数据的写入量是可以预测的——点位数量、采集频率、每条记录大小三项相乘再乘以冗余系数得到的就是数据量级。实际部署时留出 1.5 倍的余量比较安全否则后面扩容时要扩 DRBD 底层设备停机窗口会大于一次切换的时间。备份策略这块DRBD 本身不是备份它是冗余。误删除、软件 bug、数据库逻辑损坏DRBD 都会照单全收复制到备机。我始终要求在集群之外另做备份备份方式可以选择 KaiwuDB 自带的备份工具导出数据文件或者 SQL 语句定期将备份传到中心机房或对象存储。备份频率按数据价值定至少一日一备。有了这层兜底DRBD Pacemaker 的边界风险就能被完整覆盖。这套方案从设计、部署、切换到监控运维全程都是在边缘机房那些不理想的物理环境里打磨出来的。KaiwuDB 负责数据存取DRBD 负责块级镜像Pacemaker 负责故障决策三者各司其职恰好把边缘双节点高可用的几个核心问题一一化解。你现在手头如果有两台闲置服务器完全可以照着这份配置先搭一套演练环境跑一次拔电测试就知道这套方案实际用起来是什么体验了。