在这里插入图片描述

👋 大家好,欢迎来到我的技术博客!
💻 作为一名热爱 Java 与软件开发的程序员,我始终相信:清晰的逻辑 + 持续的积累 = 稳健的成长
📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。
🎯 本文将围绕ElasticSearch这个话题展开,希望能为你带来一些启发或实用的参考。
🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获!


文章目录

Elasticsearch - 跨集群复制(CCR):Elasticsearch 数据同步高级方案 🌐🔁

在现代分布式系统中,数据的高可用性、灾难恢复能力与低延迟访问已成为核心需求。当你的 Elasticsearch 集群承载着关键业务日志、实时交易数据或用户行为分析时,单点故障或区域性中断可能带来不可估量的损失。

如何确保数据在多个地理位置之间安全、高效、一致地同步?如何实现跨数据中心的读写分离?如何在不影响主集群性能的前提下完成异地灾备?

跨集群复制(Cross-Cluster Replication, CCR)正是 Elasticsearch 为此类场景提供的企业级解决方案。作为 Elastic Stack 的高级功能之一,CCR 允许你将一个索引(Leader)的数据近乎实时地自动复制到另一个远程集群(Follower),构建出灵活、可靠、可扩展的数据同步架构。

本文将深入剖析 Elasticsearch CCR 的原理、配置、使用场景与最佳实践。我们将:

  • 详解 CCR 的工作机制与数据流;
  • 演示如何通过 Kibana 和 REST API 配置跨集群复制;
  • 提供完整的 Java 客户端代码示例,实现自动化管理;
  • 对比 CCR 与其他同步方案(如 Logstash、Snapshot)的优劣;
  • 分析网络、安全、性能等生产环境关键考量;
  • 构建一个真实的多活读写分离架构案例。

无论你是 SRE、DevOps 工程师、后端开发者,还是正在规划全球部署的数据平台架构师,本文都将为你提供一套可落地、可运维、可监控的 CCR 实战指南。让我们一起揭开 Elasticsearch 高级数据同步的神秘面纱!🔐🚀


什么是跨集群复制(CCR)?核心概念解析 🧩

跨集群复制(CCR)是 Elasticsearch 自 6.5 版本引入、并在 7.x/8.x 中持续增强的一项功能。它允许你将一个索引(称为 Leader Index)中的数据自动、增量、近实时地复制到另一个集群中的索引(称为 Follower Index)。

关键特性 ✅

特性 说明
自动同步 Follower 索引自动拉取 Leader 的新操作(增删改),无需手动干预
近实时 延迟通常在秒级(取决于网络和负载)
只读 Follower Follower 索引为只读,防止数据不一致
版本兼容 Follower 集群版本必须 ≥ Leader 集群版本
基于操作日志 利用 Elasticsearch 内部的 translog(事务日志)进行增量同步
支持索引模板 可配合 ILM(索引生命周期管理)实现滚动索引的自动复制

典型应用场景 🎯

  1. 灾难恢复(DR)
    主集群(如北京)发生故障时,切换到灾备集群(如上海)继续服务。

  2. 地理就近访问(Geo-locality)
    将数据复制到不同区域的集群,用户访问本地集群,降低延迟。

  3. 读写分离
    写入集中在 Leader 集群,查询分散到多个 Follower 集群,提升读吞吐。

  4. 数据聚合与分析
    将多个业务集群的数据复制到中央分析集群,统一进行 BI 或机器学习。

  5. 蓝绿部署 / A/B 测试
    在 Follower 集群上测试新版本查询逻辑,不影响生产写入。


CCR vs 其他数据同步方案:为何选择 CCR?⚖️

在 CCR 出现之前,用户常通过以下方式实现数据同步:

方案 优点 缺点 适用场景
Logstash + JDBC/Beats 灵活,支持异构源 延迟高(分钟级),需维护管道,无事务保证 批量 ETL
Snapshot & Restore 完整备份,节省存储 全量/增量快照,恢复慢,非实时 灾备、归档
双写应用层 控制精细 应用复杂,一致性难保证,失败处理困难 简单场景
Kafka 中转 解耦,缓冲 架构复杂,需维护 Kafka 集群 高吞吐流处理
✅ CCR 近实时、自动、轻量、事务安全 仅限 ES → ES,Follower 只读 高可用、低延迟同步

💡 结论:如果你的需求是 Elasticsearch 集群之间的近实时、可靠、自动化数据复制,CCR 是最佳选择。


CCR 工作原理:数据如何从 Leader 流向 Follower?📡

理解 CCR 的内部机制,有助于排查问题和优化性能。

核心组件

  • Leader Cluster:源集群,包含可被复制的索引(需启用 index.soft_delete.enabled=true,8.x 默认开启)。
  • Follower Cluster:目标集群,主动向 Leader 拉取数据。
  • Remote Cluster Connection:Follower 集群通过此连接发现并连接 Leader 集群。
  • CCR Background Tasks:Follower 集群上的后台任务,负责拉取和重放操作。

数据同步流程

Follower Cluster Leader Cluster 1. 建立 Remote Cluster 连接 2. 请求 Leader 索引元数据 3. 拉取初始快照(首次) 返回快照数据 4. 创建本地 Follower 索引(只读) 5. 定期拉取 translog 中的新操作 返回操作序列(create/update/delete) 6. 重放操作到本地索引 loop [持续同步] Follower Cluster Leader Cluster

关键技术点

  • 基于 Sequence Number:每个操作都有全局递增序号,确保顺序一致;
  • Soft Deletes:8.x 默认启用,保留删除记录用于同步;
  • Pull-based:Follower 主动拉取,避免 Leader 被压垮;
  • 断点续传:网络中断后,从上次成功位置继续。

环境准备:搭建两个 Elasticsearch 集群 🏗️

为演示 CCR,我们需要两个独立的 Elasticsearch 集群。这里使用 Docker Compose 快速部署。

leader/docker-compose.yml

version: '3.8'
services:
  es-leader:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
    container_name: es-leader
    environment:
      - cluster.name=leader-cluster
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms1g -Xmx1g"
    ports:
      - "9200:9200"
    networks:
      - ccr-net

networks:
  ccr-net:
    driver: bridge

follower/docker-compose.yml

version: '3.8'
services:
  es-follower:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
    container_name: es-follower
    environment:
      - cluster.name=follower-cluster
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms1g -Xmx1g"
    ports:
      - "9201:9200"  # 避免端口冲突
    networks:
      - ccr-net

networks:
  ccr-net:
    driver: bridge

启动集群

# 终端1
cd leader && docker-compose up -d

# 终端2
cd follower && docker-compose up -d

等待 1–2 分钟,确认两个集群均可访问:

  • Leader: http://localhost:9200
  • Follower: http://localhost:9201

配置跨集群复制:四步走 🚶‍♂️

步骤 1:在 Follower 集群配置 Remote Cluster

Follower 需要知道如何连接 Leader。

通过 Kibana(推荐)
  1. 访问 Follower 的 Kibana(假设已部署,或使用 Dev Tools)
  2. 进入 Stack Management > Remote Clusters
  3. 点击 Add remote cluster
    • Name: leader-cluster
    • Seeds: es-leader:9300(注意:是 transport 端口 9300,不是 HTTP 9200)
  4. 点击 Save

🔒 若启用安全认证,需配置 TLS 和用户凭证。

通过 REST API
curl -X PUT "http://localhost:9201/_cluster/settings" \
-H "Content-Type: application/json" \
-d '{
  "persistent": {
    "cluster": {
      "remote": {
        "leader-cluster": {
          "seeds": ["es-leader:9300"]
        }
      }
    }
  }
}'

验证连接:

curl http://localhost:9201/_remote/info
# 应返回 leader-cluster 的状态为 "connected"

📚 官方文档:Configure Remote Clusters


步骤 2:在 Leader 集群创建可复制的索引

Leader 索引必须满足:

  • 启用 soft deletes(8.x 默认开启);
  • 不能是 .kibana 等系统索引(除非特殊配置)。
# 在 Leader 集群创建索引
curl -X PUT "http://localhost:9200/orders" \
-H "Content-Type: application/json" \
-d '{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  },
  "mappings": {
    "properties": {
      "order_id": { "type": "keyword" },
      "customer": { "type": "text" },
      "amount": { "type": "float" },
      "timestamp": { "type": "date" }
    }
  }
}'

步骤 3:在 Follower 集群启动复制

使用 _ccr/follow API 创建 Follower 索引并开始同步。

curl -X PUT "http://localhost:9201/orders_follower" \
-H "Content-Type: application/json" \
-d '{
  "remote_cluster": "leader-cluster",
  "leader_index": "orders"
}'

✅ 成功响应:{"follow_index_created": true}

此时,Follower 集群会自动创建 orders_follower 索引,并开始拉取数据。


步骤 4:验证数据同步

  1. 向 Leader 写入数据:
curl -X POST "http://localhost:9200/orders/_doc" \
-H "Content-Type: application/json" \
-d '{
  "order_id": "ORD-1001",
  "customer": "Alice",
  "amount": 299.99,
  "timestamp": "2025-04-05T10:00:00Z"
}'
  1. 查询 Follower:
curl "http://localhost:9201/orders_follower/_search?pretty"

你应该能在结果中看到刚写入的文档!


Java 客户端管理 CCR:自动化运维示例 ☕

在生产环境中,你可能需要通过程序动态管理 CCR(如创建/暂停/恢复复制)。Elasticsearch Java API Client 提供了完整支持。

Maven 依赖

<dependency>
    <groupId>co.elastic.clients</groupId>
    <artifactId>elasticsearch-java</artifactId>
    <version>8.12.0</version>
</dependency>

初始化两个客户端

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;

// Leader 客户端
RestClient leaderRestClient = RestClient.builder(
    new HttpHost("localhost", 9200)
).build();
ElasticsearchClient leaderClient = new ElasticsearchClient(
    new RestClientTransport(leaderRestClient, new JacksonJsonpMapper())
);

// Follower 客户端
RestClient followerRestClient = RestClient.builder(
    new HttpHost("localhost", 9201)
).build();
ElasticsearchClient followerClient = new ElasticsearchClient(
    new RestClientTransport(followerRestClient, new JacksonJsonpMapper())
);

创建 Leader 索引(Java)

import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;

CreateIndexRequest createRequest = new CreateIndexRequest.Builder()
    .index("products")
    .settings(s -> s
        .numberOfShards("1")
        .numberOfReplicas("0")
    )
    .mappings(m -> m
        .properties("name", p -> p.text(t -> t))
        .properties("price", p -> p.float_(f -> f))
    )
    .build();

leaderClient.indices().create(createRequest);
System.out.println("Leader index 'products' created.");

启动 CCR 复制(Java)

import co.elastic.clients.elasticsearch.ccr.PutFollowRequest;

PutFollowRequest followRequest = new PutFollowRequest.Builder()
    .index("products_follower") // Follower 索引名
    .remoteCluster("leader-cluster")
    .leaderIndex("products")
    .build();

followerClient.ccr().putFollow(followRequest);
System.out.println("CCR replication started.");

暂停与恢复复制

// 暂停
followerClient.ccr().pauseFollow(p -> p.index("products_follower"));

// 恢复
followerClient.ccr().resumeFollow(r -> r.index("products_follower"));

获取复制状态

import co.elastic.clients.elasticsearch.ccr.StatsResponse;

StatsResponse stats = followerClient.ccr().stats();
System.out.println("Active follow tasks: " + stats.followStats().numberOfSuccessfulFollowIndices());

🔗 Java API 文档:CCR Java Client


高级配置:调优 CCR 性能与可靠性 ⚙️

1. 调整拉取频率

Follower 默认每秒检查一次新操作。可通过以下参数优化:

PUT /_cluster/settings
{
  "persistent": {
    "xpack.ccr.follow_read_poll_timeout": "5s"  // 拉取间隔
  }
}
  • 值越小,延迟越低,但请求更频繁;
  • 值越大,节省资源,但延迟增加。

2. 控制批量大小

PUT /products_follower/_ccr/follow
{
  "max_read_request_operation_count": 512,   // 每次拉取最多操作数
  "max_outstanding_read_requests": 12,       // 并发读请求数
  "max_write_buffer_size": "512mb",          // 写缓冲区大小
  "max_write_buffer_count": 2147483647
}

📊 建议:高吞吐场景可增大 max_read_request_operation_count

3. 网络与安全

  • 网络带宽:确保 Leader 与 Follower 之间有足够带宽;
  • TLS 加密:生产环境必须启用 TLS;
  • 专用用户:为 CCR 创建最小权限用户(需 read + monitor 权限)。
// 在 Leader 集群创建角色
POST /_security/role/ccr_reader
{
  "cluster": ["monitor"],
  "indices": [
    {
      "names": ["*"],
      "privileges": ["read", "view_index_metadata"]
    }
  ]
}

监控与故障排查:确保 CCR 健康运行 👁️

关键监控指标

指标 说明 告警阈值
ccr.follow_pending_tasks 待处理任务数 > 0 持续增长
ccr.read_exceptions 读取异常次数 > 0
ccr.write_exceptions 写入异常次数 > 0
follower_lag_in_bytes 数据滞后字节数 > 1GB
follower_lag_in_ops 滞后操作数 > 10000

查看复制状态

# 查看所有 follow 任务
GET /_ccr/stats

# 查看特定索引状态
GET /products_follower/_ccr/stats

响应示例:

{
  "follow_stats": {
    "total_read_remote_exec_time_millis": 1200,
    "total_read_time_millis": 800,
    "total_write_time_millis": 400,
    "last_requested_seq_no": 1500,
    "last_seen_seq_no": 1500,
    "outstanding_read_requests": 0,
    "outstanding_write_requests": 0
  }
}
  • last_requested_seq_no == last_seen_seq_no 表示无滞后。

常见问题

Q1: Follower 索引无法创建?
  • 检查 Remote Cluster 是否 connected;
  • 确认 Leader 索引存在且可读;
  • 查看 Follower 日志:docker logs es-follower
Q2: 复制延迟高?
  • 检查网络延迟(ping, traceroute);
  • 增大 max_read_request_operation_count
  • 降低 Leader 写入压力。
Q3: 如何停止复制?
POST /products_follower/_ccr/unfollow

⚠️ 注意:unfollow 会关闭复制,但保留 Follower 索引数据。


架构实战:构建多活读写分离系统 🌍

假设我们有一个全球电商系统,希望:

  • 所有订单写入 美国东部(Leader)集群;
  • 用户在 欧洲亚太 通过本地 Follower 集群查询订单。

架构图

flowchart LR
    A[Web App - US] -->|Write| B[Elasticsearch\nUS-East\n(Leader)]
    C[Web App - EU] -->|Read| D[Elasticsearch\nEU-West\n(Follower)]
    E[Web App - APAC] -->|Read| F[Elasticsearch\nAPAC-SG\n(Follower)]

    B -->|CCR| D
    B -->|CCR| F

    style B fill:#ffe4b5,stroke:#333
    style D fill:#98fb98,stroke:#333
    style F fill:#98fb98,stroke:#333

实施步骤

  1. 部署三个集群:us-east, eu-west, apac-sg
  2. eu-westapac-sg 配置 Remote Cluster 指向 us-east
  3. 在两个 Follower 集群上对 orders 索引执行 follow
  4. 应用层根据用户地理位置路由查询请求。

优势

  • 写入集中,保证一致性;
  • 查询本地化,延迟 < 50ms;
  • 单区域故障不影响其他区域读取。

CCR 与索引生命周期管理(ILM)集成 🔄

实际生产中,日志或指标数据通常按天滚动(如 logs-2025-04-05)。CCR 支持自动复制新创建的索引。

步骤

  1. 在 Leader 集群创建索引模板 + ILM 策略;
  2. 在 Follower 集群创建 自动跟随模式(Auto-follow pattern)。
Leader:设置 ILM
PUT _ilm/policy/daily-logs-policy
{
  "policy": {
    "phases": {
      "hot": { "actions": { "rollover": { "max_age": "1d" } } }
    }
  }
}

PUT _index_template/logs-template
{
  "index_patterns": ["logs-*"],
  "template": {
    "settings": {
      "index.lifecycle.name": "daily-logs-policy",
      "index.lifecycle.rollover_alias": "logs-write"
    }
  }
}
Follower:设置 Auto-follow
PUT _ccr/auto_follow/logs-auto-follow
{
  "remote_cluster": "leader-cluster",
  "leader_index_patterns": ["logs-*"],
  "follow_index_pattern": "{{leader_index}}-follower"
}

现在,每当 Leader 创建 logs-2025-04-05,Follower 会自动创建 logs-2025-04-05-follower 并开始复制!

🔗 官方指南:Auto-follow Patterns


安全与权限控制:生产环境必备 🔐

CCR 涉及跨集群通信,安全至关重要。

最小权限原则

在 Leader 集群创建专用角色:

POST /_security/role/ccr_replicator
{
  "cluster": ["monitor", "manage_ccr"],
  "indices": [
    {
      "names": ["logs-*", "orders"],
      "privileges": ["read", "view_index_metadata"]
    }
  ]
}

在 Follower 集群创建用户并分配角色:

POST /_security/user/ccr_user
{
  "password": "secure_password",
  "roles": ["ccr_replicator"]
}

然后在 Remote Cluster 配置中指定用户凭证(需 TLS)。

📚 安全文档:CCR Security


替代方案思考:何时不使用 CCR?🤔

尽管 CCR 强大,但并非万能:

  • 异构数据源:若源不是 Elasticsearch,需用 Logstash 或 Kafka;
  • 双向同步:CCR 是单向的,双向需应用层协调;
  • 极低延迟要求(< 100ms):考虑同集群副本或应用缓存;
  • 成本敏感:Follower 集群需同等存储资源。

总结:构建弹性、智能的数据同步体系 🧠

通过本文,我们全面掌握了 Elasticsearch 跨集群复制(CCR)的核心能力:

  • 理解了 CCR 的工作原理与适用场景;
  • 学会了从零配置 Leader/Follower 集群;
  • 掌握了 Java 客户端自动化管理 CCR;
  • 实践了多活读写分离与 ILM 集成;
  • 了解了安全、监控、调优等生产要素。

CCR 不仅是一项技术功能,更是一种架构思维——通过数据的流动与冗余,换取系统的韧性与用户体验的提升。

当你在全球部署 Elasticsearch 集群时,CCR 就是你手中的“数据高速公路”,让信息无缝穿梭于各个角落,支撑起真正全球化、高可用的智能应用。

现在,就去你的环境中试试 CCR 吧!用几行 API,构建属于你的弹性数据同步网络。🌐✨


附录:权威资源链接

Happy Replicating! 🚀


🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨

Logo

欢迎加入我们的广州开发者社区,与优秀的开发者共同成长!

更多推荐