实现mysql和es数据同步的两大工具——Logstash和Canal

本文介绍了如何使用Logstash的JDBC插件和Canal中间件实现MySQL数据库的大规模数据同步到Elasticsearch,包括原理、配置步骤以及可能遇到的问题解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 用途

在大型实战项目开发过程中,当数据量达到比较大的规模时,不可避免的要考虑使用ElasticSearch(es)等搜索引擎来解决大量数据的查询性能压力,因此,做好mysql的数据同步变得至关重要。我所了解,并且使用的是通过Logstash和Canal中间件,来实现将数据写入到ES等中。

一、实现同步原理

1.1  Logstash

Logstash提供了一个JDBC插件,它可以定期查询数据库并捕获变化。通过配置Logstash指定连接到mysql的哪个表和es的哪个索引库,并指定对应的查询语句。当MySQL中的数据发生变化时,Logstash的JDBC插件会定时的检测到这些变化,并且迅速捕获这些新数据或者以更新的数据(根据文档id),并将其同步到es中。

注意
  • 因为涉及到数据的更新,ES和Mysql表的id字段对应关系
  • 因为是根据时间实现增量同步,所以mysql表中必须有一个包含更新或插入时间的字段

1.2  Canal

Canal中间件则是通过模拟成mysql的从库,实时接收mysql的增量数据,然后通过RESTful API将数据写入到ES中。

二、使用步骤(以es为7.14.0为例)

2.1  Logstash

  1. 下载与es对应版本的logstash-7.14.0和使用的mysql jar包
  2. 在logstash-7.14.0安装目录下创建文件夹mysqltb,将jar包放在该目录下,新建mysql.conf文件,添加内容如下:
  3. 命令行执行 logstash ‐f ../mysqletc/mysql.conf

input {

  jdbc {

      # 连接的数据库以及表

      jdbc_connection_string => ""

      # 数据库的账号和密码

      jdbc_user => ""

      jdbc_password => ""

      # mysql jar包的路径

      jdbc_driver_library => ""

      # the name of the driver class for mysql

      jdbc_driver_class => "com.mysql.jdbc.Driver"

      jdbc_paging_enabled => "true"

      jdbc_page_size => "50000"

      #以下对应着要执行的sql的绝对路径。

      #statement_filepath => ""

      statement => ""

      #定时字段 各字段含义(由左至右)分、时、天、月、年,全部为*默认含义为每分钟都更新

      schedule => "* * * * *"

       # 数据标签,用于标记不同的索引数据

      type => "user"

      # 加上jdbc时区, 要不然logstash的时间会不准确

      jdbc_default_timezone => "Asia/Shanghai"

      # 设置列名区分大小写, 默认全小写

      lowercase_column_names => "false"

  }

}

output {

  if[type] == "user"{

  elasticsearch {

      #ESIP地址与端口

      hosts => ["" ]

      #ES索引名称(自己定义的)

      index => ""

      #!!!自增ID编号,与查询语句中特有字段名一致

      document_id => "%{id}"

      # 这个必须要写不然不会同步

      document_type => "_doc"

  }}

  stdout {

      #以JSON格式输出

      codec => json_lines

  }

   

2.2  Canal

下载canal1.1.5

8.0以下版本均要开启mysql的binlog写入功能,在mysql中使用使用命令show variables like ‘%log_bin%’看是否修改成功

#开启binlog模式

log_bin=mysql-bin

binlog-format=row

#single DB binlog-ignore-db=mysql

在Canal.deployer目录下找到配置文件conf/example/instance.properties,修改如下字段

# 同步数据库地址

canal.instance.master.address=你的mysql数据库地址

# 同步数据库账号密码

canal.instance.dbUsername=你的mysql账号

canal.instance.dbPassword=你的mysql密码

修改完成后,保存,启动bin目录下面的startup.bat(linux启动startup.sh),显示Listening for transport dt_socket at address: 9099则没错

在canal.adapter目录下找到配置文件conf/application.yml,修改以下配置:

 srcDataSources:

    defaultDS:

      url: 你自己的mysql数据库地址

      username: mysql数据库账号

      password: mysql数据库密码

  canalAdapters:

  - instance: example # canal instance Name or mq topic name

    groups:

    - groupId: g1

      outerAdapters:

      - name: logger

      - name: es7 #ES同步适配器

        key: es7Key

        hosts: #ES连接地址,!!!!!!主要这里有的地方要加http:

        properties:

         mode: rest

在conf/es7目录中,新建与sql映射表名一样的yml文件

outerAdapterKey: es7Key # 这里和主配置canalAdapters.instance.groupId.outerAdapters.key下面的的key一样

dataSourceKey: defaultDS # 源数据源的key, 对应上面配置的srcDataSources中的值

destination: example  

groupId: g1

esMapping:

  _index: #ES的索引名称

  _id: _id  

  sql: ""        # sql映射

  etlCondition: "where a.c_time>={}"  

  commitBatch: 3000   #提交批大小

注意:

如果报错,可以先看日志,如果日志没有报错,并且监听到了mysql数据的改变,但是没有同步到es,可能是由于es7.x的版本问题,解决办法如下:

将canal 1.1.5.alpha-2中plugins目录下的client-adapter.es7x-1.1.5-SNAPSHOT-jar-with-dependencies.jar复制到1.1.5的plugins下

更多报错参考:canalAdapter同步至es7.x踩坑指南_client-adapter.es7x-1.1.5-snapshot-jar-with-depend-CSDN博客

三、总结

logstash使用相对比较简单,易上手,可扩展插件生态系统,支持定时存储,但是它耗资源较大,并且不能与消息队列缓存。canal实时同步存储,查询更快、更迅速,对数据库无压力,但是相对而言难些。

### Elasticsearch 与 MySQL 数据同步方案 #### 方案概述 为了实现 Elasticsearch (ES) MySQL 之间的数据同步,通常有多种技术手段可供选择。这些方法可以分为 **单向同步** **双向同步**。以下是几种常见的方式及其特点: --- #### 单向同步方案 ##### 1. 同步双写 在应用层面同时操作个存储系统,即每次更新 MySQL 的时候也直接更新 ES。这种方式的优点在于实现简单,缺点则是增加了系统的耦合度,并可能导致一致性问题。 > 应用场景下,如果需要快速部署简单的解决方案,则可以选择此方式[^2]。 ##### 2. 异步调用 通过引入消息队列(Message Queue, MQ),将 MySQL 中的变化记录发送到 MQ,再由消费者程序监听并更新至 ES。这种模式降低了服务间的耦合度,但也带来了额外的运维成本技术复杂性。 > 使用 Kafka 或 RabbitMQ 等工具可以帮助构建高可用的消息传递机制,从而提升异步调用的成功率稳定性[^3]。 ##### 3. Binlog 监听 利用 MySQL 的二进制日志(Binlog)来捕获数据库中的变更事件,并将其转发给 ES。具体来说,可以通过 Canal、Maxwell 或 Debezium 等开源工具完成这一过程。该方法无需修改现有应用程序逻辑即可实现实时增量同步。 > 开启 binlog 功能虽然会对数据库性能造成一定影响,但它提供了非常可靠的审计跟踪以及实时复制能力。 --- #### 双向同步方案 对于某些特殊需求场景可能涉及从 ESMySQL 的反向同步或者者间相互作用的情况,此时就需要考虑更复杂的架构设计。例如,在电商领域中商品库存管理可能会涉及到跨平台订单处理等业务流程。 一种可行的办法是借助专门用于多源异构环境下的数据集成产品——如 CloudCanal 来搭建完整的双向同步链条。它不仅支持标准 SQL 查询语句转换成目标端可识别的操作命令序列,还具备自动解决潜在冲突的能力。 > 当面对频繁交互且要求强一致性的场合时,采用专业的中间件可能是最优选项之一[^1]。 --- #### 推荐工具对比表 | 工具名称 | 主要特性 | 适用范围 | |----------------|----------------------------------------------------------------------------------------------|-----------------------------------| | Canal | 基于 MySQL Binlog 提供准实时的数据订阅与分发 | 小规模项目 | | Maxwell | 类似于 Canal,但更加轻量 | 对延迟容忍较高的情况 | | Debezium | 支持更多类型的数据库作为源头 | 型分布式系统 | | Logstash | ELK Stack 组件之一,灵活配置输入输出插件 | 日志采集及初步加工 | | CloudCanal | 商业化软件,专注于企业多云/混合环境下规模关系型数据库与其他 NoSQL 存储之间无缝衔接 | 关键任务驱动的企业内部信息化建设 | --- #### 同步策略总结 - 如果追求低延迟能力并且愿意承担一定的基础设施投入,则推荐基于 Binlog 的监听方式; - 若希望减少开发工作量而接受稍高的失败概率的话,那么可以直接采取同步双写的办法; - 考虑到长期维护便利性扩展灵活性因素,选用成熟的第三方框架往往是明智之举。 ```python import pymysql from elasticsearch import Elasticsearch def sync_mysql_to_es(mysql_conn_info, es_host): """ A simple example of syncing data from MySQL to Elasticsearch. Args: mysql_conn_info (dict): Connection parameters for the MySQL database. es_host (str): Hostname or IP address where Elasticsearch is running. Returns: None """ # Connect to MySQL and fetch records connection = pymysql.connect(**mysql_conn_info) cursor = connection.cursor() query = "SELECT id, name FROM users" cursor.execute(query) rows = cursor.fetchall() # Initialize an Elasticsearch client es_client = Elasticsearch([es_host]) # Index each record into Elasticsearch for row in rows: doc_id, doc_name = row document = {"id": doc_id, "name": doc_name} es_client.index(index="users", id=doc_id, body=document) sync_mysql_to_es({"host": "localhost", "user": "root", "password": "", "db": "test"}, "http://localhost:9200") ``` ---
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值