单集群的副本只能防节点故障,防不了机房断电、区域中断与人为误删。跨集群复制(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 是核心指标,持续增长需排查 |
| 监控告警 | 防静默失效,定期演练与一致性校验 |
跨集群复制把「数据不丢」从单集群内的副本提升到跨地域的实时复制,是灾备体系的核心组件。它的价值不在于平时,而在于故障发生的那几分钟——只有演练过的切换流程才靠得住。灾备与备份的配合见《部署运维与备份恢复》,集群健康与容量规划见《集群运维与监控》,数据同步的整体架构见《搜索服务架构:从索引到容错》。
延伸阅读
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。