Elasticsearch 如何与 MySQL 集成(数据同步)?

MySQL 数据同步到 Elasticsearch 的四种方案:Logstash JDBC 插件定时拉取、监听 binlog(Canal/Debezium)实时同步、应用双写、以及 CDC 平台。本文对比各方案并给出 Logstash 配置示例。

最佳实践
Elasticsearch 如何与 MySQL 集成(数据同步)?封面

主流方案是两类:定时轮询——Logstash 的 jdbc input 按更新时间增量拉取;实时同步——Debezium/Canal 捕获 binlog,再由适配的消费者/连接器写入 ES。小表低频用前者,大表实时性要求高用后者。

方案一:Logstash JDBC 定时拉取

input {
  jdbc {
    jdbc_connection_string => "jdbc:mysql://mysql:3306/shop"
    jdbc_user => "reader"
    jdbc_password => "${MYSQL_READER_PASSWORD}"
    jdbc_driver_library => "/opt/mysql-connector-j.jar"
    jdbc_driver_class => "com.mysql.cj.jdbc.Driver"
    use_column_value => true
    last_run_metadata_path => "/var/lib/logstash/products-jdbc.yml"
    statement => "SELECT * FROM products WHERE updated_at >= :sql_last_value ORDER BY updated_at, id"
    schedule => "*/1 * * * *"
    tracking_column => "updated_at"
    tracking_column_type => "timestamp"
  }
}
output {
  elasticsearch {
    hosts => ["es:9200"]
    index => "products"
    document_id => "%{id}"     # 用主键当文档 ID,重复同步变更新
  }
}

每个 JDBC input 使用独立、持久且可写的 checkpoint 路径。相同时间戳用 >= 回放边界可减少遗漏,但不能捕获所有迟提交/回填时间的更新;需重叠窗口与对账,或选择 CDC。

关键技巧:sql_last_value 记录上次同步位点实现增量;document_id 用主键让重复写入变成更新而不是重复文档,但迟到的旧事件仍可能覆盖新值,需要顺序、版本控制或对账。

方案二:binlog 实时同步

Debezium(Kafka Connect)或 Canal 监听 MySQL binlog,再通过适配 sink/消费者处理主键、更新与删除。实际延迟取决于链路负载和积压,但架构复杂度高(多一套 CDC 组件)。

方案三:应用双写

业务代码写完 MySQL 顺手写 ES。简单但耦合——ES 挂了影响主流程,仅重试不能保证事务一致性,需幂等、顺序与失败补偿;可靠场景可用同一事务写 outbox 再异步投递。

选型建议

场景 方案
报表/搜索,分钟级延迟可接受 Logstash JDBC
搜索要求准实时 binlog CDC
极小项目 应用双写

常见问题(FAQ)

Q:删除的数据怎么同步? 轮询方案感知不到物理删除——业务上改软删除(加 deleted 标记),或 CDC 可捕获 DELETE,但下游仍需把删除事件映射为 ES 删除;软删除标记也需明确处理策略。

Q:全量初始化怎么做? 全量快照与增量位点必须协调,避免导入期间的更新/删除遗漏;可使用 CDC 一致快照流程,轮询方案则需建立可靠水位、回放和对账,不能简单去条件再切换。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台