前置问题与边界

HBase 跨集群 Replication 复制的是 WAL edit。源集群的 RegionServer 把符合条件的 edit 放入复制队列,由 replication source 推送到 peer 集群。这个过程是异步的,常用于容灾、迁移、异地读和下游同步;它不把两个集群变成一个强一致数据库。

本篇回答一个核心问题:WAL edit 如何异步复制,顺序、延迟、冲突和故障切换的边界是什么。RegionServer 崩溃后的本地 WAL 恢复见第 11 篇;Snapshot 和 Backup 见第 13 篇。

复制路径图

flowchart LR
    A[Client write] --> B[Source RegionServer]
    B --> C[Source WAL]
    C --> D[Replication queue]
    D --> E[ReplicationSource]
    E --> F[Peer cluster RPC]
    F --> G[Sink RegionServer]
    G --> H[Peer table]
    D --> I[Backlog if peer unavailable]

复制链路的起点仍然是源集群 WAL,不是直接扫描 HFile,也不是依靠 HDFS 复制目录。WAL edit 被过滤、排队、批量发送和在 peer 端应用。同步延迟、失败重试和队列积压都属于这条链路的常态风险。

关键对象和状态

对象 作用 边界
Replication peer 目标集群配置 只描述复制目标和策略
WAL edit 复制输入 已写入源集群的 mutation 记录
Replication queue 源端队列 peer 不可用时产生积压
ReplicationSource 源端推送线程 异步发送 edit
Sink peer 端接收路径 把 edit 应用到目标表
Column family scope 列族复制范围 只有配置为复制的列族进入链路

跨集群 replication 与 region replication 不是同一件事。跨集群 replication 面向 peer 集群;region replication 面向同一集群内的 Region 副本和 timeline read 等能力。两者解决的问题不同,不能混写。

顺序和延迟

默认跨集群 replication 是异步、at-least-once、非全局有序的 WAL edit 传播。WAL edit 在源 RegionServer 上具有日志顺序,复制也围绕 WAL 队列推进;这只能支撑局部队列上的相对顺序,不能推导成全局跨表、跨 Region、跨集群强顺序。

Region move 或 RegionServer failure 会让旧 WAL source 和新 WAL source 在一段时间内并发推进。业务如果依赖同一 row key 在 peer 端严格按源端顺序应用,需要显式使用串行复制。HBase 2.1+ 支持为 peer 配置 SERIAL => true;默认 peer 的 serial replication 为 false,不能把默认复制链路写成有序提交协议。

复制延迟不是异常本身。peer 不可用、网络抖动、sink 端写入慢、源端 WAL 量大,都会形成 backlog。监控应关注 replication age、queue size、shipped ops、failed batches 这类指标,而不是把“源端写入成功”当成“peer 已经可读”。

模式提炼:异步复制是“先记录事实,再传播事实”。公式是 commit(local_log) -> enqueue -> ship(peer) -> apply(remote)。消息队列 outbox、数据库 CDC、搜索索引同步都属于同类设计。它提供的是最终到达和可重放线索,不提供同步提交确认;需要顺序时,要把 serial 配置当成额外约束单独验证。

冲突和故障切换

单向复制最清楚:源集群负责写,peer 集群接收。双向复制或多源写入会引入冲突。HBase replication 不应被描述为自动冲突解决系统;相同 row key、family、qualifier 和 timestamp 的写入冲突,或者两端应用写入次序不一致,都需要业务层设计策略。

故障切换也不是“peer 自动成为主库”。切流需要外部决策:冻结或隔离旧源写入、确认复制积压、切换客户端配置、处理回切和冲突。RPO 取决于尚未复制的 WAL edit;RTO 取决于检测、确认、路由切换和应用恢复流程。

最小实验

UNVERIFIED_RUNTIME:以下步骤需要两个可丢弃 HBase 2.6.6 集群,当前环境未运行,未采集输出。

实验需要源集群和 peer 集群都准备同名表。源集群的列族打开 replication scope,peer 集群只创建普通目标表:

1
hbase shell
1
create_namespace 'lab'
1
create 'lab:t12_rep_src', {NAME => 'cf', REPLICATION_SCOPE => '1'}
1
hbase shell
1
create_namespace 'lab'
1
create 'lab:t12_rep_src', 'cf'

源集群添加 peer 时,CLUSTER_KEY 按目标 ZooKeeper quorum、端口和 znode 配置填写;默认 peer 用于观察普通异步复制,需要同一 peer 使用 serial replication 时,创建 peer 时显式声明 SERIAL => true

1
add_peer 'dr', CLUSTER_KEY => 'zk-peer.example:2181:/hbase'
1
add_peer 'dr_serial', CLUSTER_KEY => 'zk-peer.example:2181:/hbase', SERIAL => true

源集群写入测试行:

1
put 'lab:t12_rep_src', 'r1', 'cf:q', 'v1'

peer 集群读取同一行:

1
get 'lab:t12_rep_src', 'r1'

实验观察点只包括:源端写入后 peer 端最终可见、peer 暂停时队列积压、peer 恢复后队列下降。不得记录未经复测的复制毫秒数。

失败恢复

失败场景 可恢复内容 不自动解决的内容
peer 短暂不可用 源端 replication queue 保留待发送 edit 应用侧读 peer 的陈旧数据
源 RegionServer 崩溃 第 11 篇的 WAL 恢复先恢复本地服务,旧新 WAL source 可能并发 默认 peer 端非全局有序,SKIP_WAL 写入也无法复制
双向写冲突 WAL edit 仍会传播 业务冲突合并策略
灾备切流 peer 可作为新写入口 客户端路由、旧源隔离、回切策略

复制链路的可靠性建立在 WAL、队列、重试和 peer 可用性上。它适合降低灾难场景的数据损失,不适合替代同步复制事务。

工程迁移

目标 HBase replication 用法 设计提醒
异地灾备 主集群写,灾备集群复制接收 明确 RPO/RTO 和切流流程
在线迁移 新集群作为 peer 追数据 切换前核对积压和校验抽样
异地读 peer 承担读流量 接受异步延迟和陈旧读
下游同步 WAL edit 进入外部系统 目标端幂等写和重试要独立设计

模式速查:听到“先写主库,再同步到另一个系统”,优先画出本地提交、队列、发送、应用、回压五个状态。少一个状态,故障处理就容易写成口号。

常见误解

  • “Replication 保证强一致”不准确;它是异步复制,peer 可读时间晚于源端提交。
  • “默认 replication 保证全局有序”不准确;默认是 at-least-once、非全局有序,serial replication 需要在 peer 上显式启用。
  • “两个集群可以随便双写”不准确;冲突处理不是 HBase 自动事务语义。
  • “HDFS 目录复制等于 HBase replication”不准确;HBase replication 以 WAL edit 和 peer 配置为核心。
  • “region replication 和跨集群 replication 一样”不准确;前者是同集群 Region 副本能力,后者是跨集群 WAL edit 传播。

练习

  • 画出 peer 网络中断 10 分钟时的队列、源表、peer 表状态。
  • 设计一个从旧集群迁移到新集群的只读校验步骤,不使用性能数字。
  • 给双向复制下的同一 row key 冲突写一份业务处理规则。

系列导航

参考资料