跨集群复制与灾备:CCR 跟随索引、故障切换与双活权衡

系统讲解 Elasticsearch 跨集群复制(CCR):跟随索引与 leader/follower 机制、auto-follow 模式、故障切换与提升流程、双活架构权衡,以及带宽与延迟的容量考量。

单集群的副本只能防节点故障,防不了机房断电、区域中断与人为误删。跨集群复制(Cross-Cluster Replication,CCR)把索引的变更从主集群持续同步到备集群,让备集群随时保有可查可用的数据副本,从而支撑异地灾备、读写分离与就近访问。它基于 Lucene 的段级复制,同步的是「索引变更」而非「文档变更」,因此比应用层双写更可靠、更省带宽。本文从 CCR 的机制讲起,覆盖跟随索引、auto-follow、故障切换、双活权衡与容量规划。

1. CCR 的概念与适用场景

一句话总结: CCR 在主集群(leader)与备集群(follower)之间做段级复制,实现异地灾备、读写分离与就近查询。

1.1 与副本的区别

普通副本位于同一集群,随分片分配与恢复机制同步,防的是节点与磁盘故障。CCR 跨集群复制,防的是集群级与区域级故障。两者互补:集群内用副本保可用,集群间用 CCR 保灾备。

1.2 典型场景

  • 异地灾备:主集群故障时,备集群可提升为可写并接管业务。
  • 读写分离:写主集群,读备集群,分担查询压力。
  • 就近访问:多地域部署,用户查本地备集群,降低跨区延迟。
  • 集中汇聚:多个边缘集群把数据汇聚到中心集群做统一分析。

1.3 段级复制的优势

CCR 复制的是 Lucene 段文件而非逐条文档,因此:

  • 带宽消耗低,大段一次性传输,避免逐条文档的协议开销。
  • 保序可靠,复制的是已经落盘的结构,不会出现文档乱序。
  • 不占用写入线程池,复制在独立通道进行。

1.4 前置条件

CCR 需要 Elasticsearch 白金版或企业版许可,且需要配置远程集群连接。跨集群连接基于 remote_cluster_client 角色节点,主集群至少一个节点具备该角色。

2. 跟随索引与 leader/follower

一句话总结: follower 索引跟随 leader 索引,只读接收复制,所有写入只能发生在 leader 侧。

2.1 配置远程集群

先在备集群注册远程集群连接:

PUT /_cluster/settings
{
  "persistent": {
    "cluster.remote.leader-cluster.seeds": ["leader-host-1:9300", "leader-host-2:9300"]
  }
}

seeds 是主集群节点的传输端口地址,只需少量节点做引导。

2.2 创建 follower 索引

PUT /follower-logs/_ccr/follow
{
  "remote_cluster": "leader-cluster",
  "leader_index": "logs-000001"
}

follower 索引是只读的,所有写入必须在 leader 上执行。尝试直接写 follower 会返回错误,这是设计约束而非缺陷。

2.3 复制机制

CCR 的复制流程:leader 侧把新的段与 translog 变更推送给 follower,follower 拉取并应用。复制是拉取模式(follower 主动拉),因此 follower 侧需要能访问 leader,反之不一定需要。

2.4 一致性与延迟

CCR 是异步复制,follower 落后 leader 有一个可观测的延迟(follower lag)。延迟受网络带宽、变更速率与 follower 集群负载影响。多数灾备场景容忍秒级延迟,但要求「最终一致」而非「强一致」。

2.5 暂停与恢复

POST /follower-logs/_ccr/pause_follow
POST /follower-logs/_ccr/resume_follow

暂停用于维护或切换期间冻结复制,恢复后从上次位置继续,不会丢数据。也可以 unfollow 彻底断开,断开后 follower 变成普通可写索引。

2.6 follower 索引的写入限制

follower 索引不能直接写入,但可以调整部分设置(如副本数、refresh 间隔)。如果业务需要在备集群写入(例如就近写入),那就不适合用 CCR,应考虑双写或双向同步方案。

3. auto-follow 模式

一句话总结: auto-follow 按索引模式自动跟随新建的滚动索引,让时序数据流的灾备无需人工干预。

3.1 为什么需要 auto-follow

日志与时序数据会不断滚动出新索引。手工为每个新索引创建 follower 不现实,auto-follow 通过模式匹配自动完成。

3.2 创建 auto-follow 模式

PUT /_ccr/auto_follow/logs-pattern
{
  "remote_cluster": "leader-cluster",
  "leader_index_patterns": ["logs-*"],
  "follow_index_pattern": "{{leader_index}}-follower",
  "max_outstanding_read_requests": 12
}

新索引一旦在 leader 上出现且匹配 logs-*,备集群自动创建对应 follower。

3.3 命名策略

follow_index_pattern 支持 {{leader_index}} 占位符,可以加后缀(如 -follower)或前缀区分。命名要保证唯一且不与本地索引冲突。

3.4 与 ILM 的配合

时序索引会滚动、降冷、删除。auto-follow 需要与 ILM 协调:follower 侧也应配置对应的生命周期,但删除动作要谨慎——leader 删除索引时,follower 不会自动删除,需要单独管理。常见做法是 leader 与 follower 使用同名 ILM 策略,删除窗口错开。

3.5 排除与过滤

可以用 leader_index_patterns 的正向匹配加排除模式,只跟随需要的索引,避免把系统索引或无关索引也复制过去,浪费带宽。

3.6 auto-follow 的运维

查看当前 auto-follow 模式与状态:

GET /_ccr/auto_follow
GET /_ccr/stats

统计里能看到每个模式的跟随成功数与失败数,失败通常源于命名冲突或权限不足。

4. 故障切换与提升

一句话总结: 主集群故障时,把 follower 索引提升(promote)为可写,切换应用写入目标,是灾备接管的核心动作。

4.1 提升前的准备

提升前必须先 pause_follow 或确认 leader 已不可用,否则会出现「两个可写索引」导致数据分叉。标准流程:确认 leader 故障 → 暂停所有 follower → 检查 lag 是否可接受 → 逐索引提升。

4.2 提升 follower

POST /_ccr/follow_info/follower-logs
POST /follower-logs/_ccr/unfollow

unfollow 让 follower 脱离 CCR,成为普通可写索引。也可以先暂停再提升,具体命令随版本略有差异,核心是解除只读与复制绑定。

4.3 切换应用流量

提升后要切换应用:写入指向新的主集群(原 follower),查询可以继续用别名。前提是别名抽象到位——应用只认别名,切换时改别名指向或改集群地址,无需改代码。

4.4 别名与路由的抽象

灾备切换的顺畅程度取决于前期抽象:

  • 应用统一走别名,不直连索引名。
  • 集群地址通过配置中心下发,支持热切换。
  • 写路径与读路径分离,可分别切换。

4.5 回切流程

主集群恢复后,要把数据同步回去。此时原 follower 已成为新 leader,需要重新建立复制方向:在原 leader 上创建 follower 跟随新 leader。回切同样要经历暂停、提升、切流量三步,且要处理切换期间双写的冲突。

4.6 切换演练

灾备方案必须定期演练。演练内容:模拟主集群故障、执行提升、切换流量、验证查询、回切。不演练的方案在真故障时大概率失败——脚本过期、权限缺失、别名配置遗漏都是常见问题。

4.7 数据丢失窗口

异步复制意味着提升时 follower 可能落后若干秒,这段数据会丢失。对可接受的数据丢失量(RPO)要有明确预期,并通过监控 lag 确保它在可接受范围内。

5. 双活架构权衡

一句话总结: 双活让两个集群都可读写,代价是冲突处理与复杂度,多数场景用「主备」而非「双活」更划算。

5.1 双活的诱惑与代价

双活能提升资源利用率与就近写入体验,但引入的核心难题是冲突:同一文档在两个集群被并发修改,谁是最终版本?Elasticsearch 的 CCR 是单向复制,原生不支持双向同步的冲突解决。

5.2 双活的实现方式

  • 按租户/地域分片写入:不同地域写不同索引,互不冲突,只做单向复制汇聚。
  • 应用层双向同步:应用同时写两个集群,冲突由应用或版本号解决,复杂度高。
  • 单向 + 只读备:备集群只读,不做双活,这是最稳妥的形态。

5.3 冲突解决策略

如果一定要双活,常见策略是「最后写入胜出」(用时间戳或版本号)、「主地域优先」(某地域的写入优先),或业务层去重。这些策略都要在应用层实现,Elasticsearch 不提供。

5.4 什么时候值得双活

只有当「就近写入带来的延迟收益」或「两地都必须能写」是硬需求时才值得。多数业务「写主读备」就够用:写入集中在主集群保证一致性,读取分散到备集群降低延迟。

5.5 主备与双活对比

维度主备双活
一致性单向清晰需冲突解决
复杂度低高
资源利用备集群可只读服务双写充分利用
故障切换单向提升双向切换
适用大多数灾备多地域强需求

5.6 渐进式演进

可以从主备起步,把备集群开放只读查询,既验证链路又提升资源利用率;等业务确实需要双活,再评估冲突解决成本。不要一开始就上双活。

6. 带宽与延迟考量

一句话总结: CCR 的成本主要是跨集群带宽,复制延迟由带宽、变更速率与 follower 处理能力共同决定。

6.1 带宽估算

带宽需求 ≈ 写入速率 × 副本系数 × 冗余。例如主集群每天写入 100GB 原始数据,段级复制会带来接近该量级的跨区流量。跨区带宽通常昂贵,必须提前估算并做容量预留。

6.2 降低带宽的手段

  • 只复制必要索引:auto-follow 精确匹配,避免复制系统索引与无关数据。
  • 压缩传输:CCR 传输段文件,段本身已压缩,但网络层仍可启用压缩。
  • 错峰复制:写入高峰期复制压力大,可通过 ILM 让 force merge 在低峰进行,减少复制量。
  • 减少段数量:段越多,复制的元数据开销越大,force merge 能降低复制频率。

6.3 延迟的观测

GET /follower-logs/_ccr/stats

关注 follower_lag(落后时间)与 operations_written。lag 持续增长说明 follower 追不上,需要排查带宽、follower 负载或 leader 变更速率。

6.4 影响延迟的因素

  • 网络 RTT:跨区往返延迟影响拉取效率,高延迟链路要考虑并发读请求数。
  • follower 集群负载:follower 同时在服务查询时,复制会与之争抢资源。
  • 变更突发:主集群批量导入时,复制会出现脉冲式高峰。

6.5 复制与查询的资源竞争

follower 集群既接收复制又服务查询,两者共享磁盘与线程。灾备集群若同时承担读流量,要预留足够资源给复制,否则 lag 会持续拉大。可用节点标签把复制与查询的负载分开。

6.6 容量规划

规划要点:跨区带宽预留峰值余量、follower 集群磁盘与 leader 相当或略小(可更激进的 ILM)、预留故障切换时的写入容量。灾备集群不是「只存不查」的仓库,切换后它要承担全部负载。

7. CCR 运维与监控

一句话总结: CCR 运维关注复制状态、lag、失败重试与权限,任何一项异常都可能导致灾备失效而无人察觉。

7.1 状态查看

GET /_ccr/follow_info
GET /_ccr/stats
GET /_cat/indices?v&h=index,health,status,docs.count

follow_info 列出所有 follower 及其 leader、状态与 lag;stats 给出读写操作数与字节数。

7.2 常见故障

  • follower 索引变红:通常因 follower 集群磁盘或节点不足,复制写入失败。
  • lag 持续增长:带宽不足或 follower 负载过高。
  • 复制停止:远程集群连接断开,检查 cluster.remote 配置与网络连通性。
  • 权限错误:follower 侧缺少 manage_ccr 权限,或远程集群连接未正确授权。

7.3 监控告警

对以下指标设告警:lag 超过阈值、复制操作失败、follower 索引健康非绿、远程连接不可用。灾备链路最怕「静默失效」——链路断了但没人知道,真出事时才发现备集群数据是几个月前的。

7.4 定期演练与校验

除了切换演练,还要定期校验数据一致性:对比 leader 与 follower 的文档数、索引大小、抽样查询结果。段级复制理论上保证一致,但链路中断期间的数据缺失需要被发现。

7.5 版本与许可

CCR 需要相应版本的许可证,且主备集群版本要兼容。升级时要注意顺序:通常先升级备集群再升级主集群,避免复制协议不兼容。具体顺序以官方升级文档为准。

7.6 与快照的关系

CCR 是实时复制,快照是周期性备份,两者互补:CCR 应对集群故障快速切换,快照应对数据误删与历史回溯。灾备体系应同时具备两者,CCR 保证「最近的数据在」,快照保证「过去的数据能找回来」。

8. 总结

环节要点
CCR 定位跨集群段级复制,防集群与区域故障
follower 索引只读接收复制,写入只能在 leader
auto-follow按模式自动跟随滚动索引,时序灾备必备
故障切换暂停复制后提升 follower,切换应用流量
别名抽象应用只认别名,切换无需改代码
双活权衡冲突解决复杂,多数场景主备更划算
带宽估算接近写入量级,跨区成本需提前规划
延迟观测follower lag 是核心指标,持续增长需排查
监控告警防静默失效,定期演练与一致性校验

跨集群复制把「数据不丢」从单集群内的副本提升到跨地域的实时复制,是灾备体系的核心组件。它的价值不在于平时,而在于故障发生的那几分钟——只有演练过的切换流程才靠得住。灾备与备份的配合见《部署运维与备份恢复》,集群健康与容量规划见《集群运维与监控》,数据同步的整体架构见《搜索服务架构:从索引到容错》。

延伸阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「elasticsearch」更多文章

  1. 可搜索快照与冻结层:把冷数据放进对象存储还能查
  2. 分页与深度分页:from/size、search_after、PIT 与 scroll
  3. 嵌套与父子关联查询:nested、join 字段与性能取舍