存储双活上线后,出现数据不一致的案例并不少见。问题往往不在硬件层面,而是团队把双活理解成两台阵列同时提供读写,忽略了复制链路本身的设计。双活的目标是让两个站点同时承载业务,但数据同步链路是这条目标的生命线。链路抖动、复制协议选择不当、心跳网络与数据网络未隔离,都会让双活架构在故障切换时暴露出数据丢失或服务中断。因此,必须先明确数据同步的模式边界,再谈高可用。

一、同步复制、异步复制与半同步的边界
同步复制保证每个写请求必须在两个站点都落盘后才返回成功。优点是RPO为零,缺点是链路延迟直接叠加到写入延迟。跨机房通常链路往返时间RTT超过1毫秒后,同步复制会让数据库事务性能明显下降。异步复制则是主站点先返回成功,再异步传输到备站点,优点是性能好,缺点是故障时可能丢失最后一个时间窗的数据。半同步复制介于两者之间,只要备站点收到并写入内存缓存即确认,但未完全落盘,适合中等距离园区。
多数存储双活方案支持同步与异步策略动态切换。例如采用存储网关做卷镜像时,可以针对不同LUN设置不同复制模式。生产环境常把核心交易库放在同步复制卷,日志归档放在异步复制卷。此外,同步复制对链路质量要求极高,光模块抖动、交换机丢包都会导致写IO悬挂,因此需要搭配链路聚合和冗余路径。
| 复制模式 | 数据持久化确认点 | RPO | 适用场景 |
|---|---|---|---|
| 同步复制 | 双端落盘 | 0 | 核心交易、金融账务 |
| 半同步复制 | 备端内存确认 | 接近0 | 同城园区、低延迟网络 |
| 异步复制 | 主端落盘 | 秒级到分钟级 | 归档、非关键业务 |
二、脑裂是怎么发生的,仲裁机制如何兜底
当双活站点之间的心跳链路中断,但两个站点自身都正常时,双方都会认为对方已经失效,于是各自提升为主节点并继续接收写入,这就是脑裂。脑裂会导致同一块卷出现两份独立数据,恢复时只能丢弃其中一份,造成数据丢失。要防止脑裂,不能只依赖一条心跳线,需要至少两条独立心跳通道,并增加仲裁节点。
仲裁机制的核心是多数派原则。常见部署会引入第三个轻量节点作为见证,当站点之间的数据链路与心跳同时断开时,只有能连通仲裁节点的站点才能继续提供服务。另一个站点会触发IO悬挂,所有写入被阻塞,直到链路恢复或人工强制切换。这种方式虽然牺牲了一部分可用性,但避免了数据分叉。某些存储双活方案还支持按LUN粒度设置仲裁策略,比如关键卷使用强仲裁,非关键卷允许自动切换。
下面是一个简化的双活仲裁配置思路,以存储集群的投票权重为例,其中数据链路和心跳链路分别使用不同网段,仲裁节点只参与投票,不承载业务卷。
cluster:
name: active-active-storage
quorum:
mode: majority
witness:
host: 192.168.100.3
weight: 1
nodes:
- id: node-a
weight: 1
paths:
data: 10.10.1.0/24
heartbeat: 10.10.2.0/24
- id: node-b
weight: 1
paths:
data: 10.10.1.0/24
heartbeat: 10.10.2.0/24
这个配置里,两个存储节点和仲裁节点各占一票。数据链路断开但心跳链路正常时,心跳层可以感知对方存活,自然不发生脑裂。当数据链路和心跳链路同时断开时,能连通仲裁节点的那个存储节点才能继续写入,另一个节点必须悬挂IO。这样虽然降低了极端情况下的可用性,但换来了数据一致性。
三、DRBD配置示例:从协议到缓存策略
开源方案中,DRBD常被用来构建Linux块设备双活或主备复制。双活场景下,DRBD通常运行在protocol C,表示只有双端落盘后才返回写成功,这也是一种同步复制模式。配置中需要关注磁盘、网络和元数据三部分。下面给出一个精简但完整的资源定义。
resource r0 {
protocol C;
device /dev/drbd0;
disk /dev/sdb1;
meta-disk internal;
net {
cram-hmac-alg sha256;
shared-secret "replace-me";
timeout 60;
connect-int 10;
ping-int 10;
max-buffers 2048;
max-epoch-size 2048;
}
syncer {
rate 120M;
verify-alg crc32c;
}
on node-a {
address 192.168.1.1:7789;
node-id 0;
}
on node-b {
address 192.168.1.2:7789;
node-id 1;
}
}
在双活场景中,protocol C虽然保证双端落盘,但是一旦备端链路抖动,写请求会被阻塞,可能把前端业务拖死。这时可以在DRBD之上配合多路径和IO超时策略,或者临时降级为protocol B。不过降级协议意味着RPO不再为零,需要业务方明确承受范围。缓存策略同样关键,磁盘写缓存和阵列掉电保护必须匹配,否则主端刚确认落盘、备端仍在缓存中就掉电,会造成双活数据不一致。
网络参数方面,timeout、connect-int和ping-int共同决定链路故障的检测时长。如果心跳检测过短,网络抖动会导致频繁切换;如果检测过长,故障期间上层应用会持续卡顿。实际生产环境通常需要结合交换机端口统计和存储时延基线反复调参,不能照搬默认值。
四、数据校验、演练与完整容灾链条
同步链路正常不代表数据一定一致。存储双活上线后,还需要定期做在线校验,比较两个站点的块级数据是否一致。DRBD提供verify-alg参数做后台校验,但校验会占用链路带宽,应放在业务低谷执行。一些存储阵列支持针对LUN的一致性组快照,可以在快照基础上对比元数据和数据块指纹。块级校验只能发现物理存储不一致,无法发现上层文件系统或数据库逻辑错误,所以需要结合应用层校验。
更重要的一点是,双活不能替代备份。双活解决的是站点级硬件故障或链路故障下的业务连续性,但无法应对误删除、勒索软件、逻辑错误和软件缺陷。例如管理员误删了某个库,双活会非常高效地把删除同步到两个站点,加速数据消失。因此完整容灾链条中,必须保留定期快照、定时备份和异地副本。双活可以保证RPO接近零,但备份策略决定的是更长时间跨度的恢复能力。
上线双活之前,至少要进行三类演练:链路中断演练、单站点掉电演练、仲裁节点失效演练。很多团队只测试了存储切换,没有测试应用切换,导致故障时业务连接还指向旧站点。切换预案应包含DNS或VIP漂移,以及数据库和消息队列的恢复顺序。只有把存储双活放进业务连续性整体设计里,数据同步才能真正发挥价值。