通过Canal、Canal adapter将MySQL数据同步到ES

通过Canal将MySQL数据同步到ES

软件配置:
  • Mysql 8.2 (阿里云服务器中docker镜像内)

  • ES 7.17 (本地WSL docker)

  • Canal 1.1.6 (本地wsl)

  • Canal-adapter 1.1.6 (本地wsl)

  • jdk 11 (本地wsl)

原理

Canal 本质是在"假装自己是 MySQL 的从库",读取 binlog,再把数据变更解析出来。MySQL 有一个核心机制:

1. binlog(数据库变更日志)

MySQL 每次执行:

  • INSERT

  • UPDATE

  • DELETE

都会写入 binlog。

复制代码
binlog 可以理解为:所有数据变更的“操作日志

2. binlog 有三种格式

类型 说明 Canal用哪种
STATEMENT 记录 SQL ❌ 不稳定
ROW 记录行变化 ✅ 必须用
MIXED 混合 ❌ 不推荐

👉 Canal 依赖 ROW 格式

因为它记录的是:

复制代码
before / after 的数据变化

而不是 SQL。

三、MySQL 主从复制机制(关键底层)

MySQL 原生有一套机制:

主库(Master)

  • 写 binlog

从库(Slave)

  • 连接 Master

  • 拉 binlog

  • 执行 SQL

四、Canal 的"关键伪装"

⭐ Canal 做了一件非常巧妙的事情:

👉 它伪装成 MySQL 从库

Step 1:建立连接

Canal 对 MySQL 说:

复制代码
我是一个 Slave
我要同步数据

MySQL 会启动一个:

复制代码
binlog dump thread

Step 2:MySQL 推送 binlog

MySQL 开始把 binlog:

复制代码
持续发送给 Canal

就像"直播推流"。


Step 3:Canal 接收 binlog

Canal 收到的是这种原始数据:

复制代码
TableMapEvent
WriteRowsEvent
UpdateRowsEvent
DeleteRowsEvent

👉 注意:这是 底层事件,不是 SQL


Step 4:Canal 解析 binlog

Canal 做的事情:

复制代码
binlog event → 结构化数据

例如:

复制代码
{
  "table": "user",
  "action": "update",
  "before": {"name": "Tom"},
  "after": {"name": "Tom2"}
}

五、Canal Adapter 做什么

Canal 只负责:

"读 binlog + 解析数据"

但不会写 ES。

Adapter 的工作:

Step 1:接收 Canal 数据

拿到结构化变更:

复制代码
update user set name='Tom2'

Step 2:转换成 ES 文档

例如:

复制代码
{
  "_id": 1,
  "name": "Tom2",
  "age": 20
}

Step 3:写入 ES

通过 Bulk API:

复制代码
POST /_bulk

批量写入 Elasticsearch。


六、整个链路本质

一句话总结:

复制代码
MySQL binlog(变化日志)
    ↓
Canal(模拟从库读取 binlog)
    ↓
解析 binlog event
    ↓
Adapter(转换数据结构)
    ↓
Elasticsearch(存储+检索)

下面为操作步骤:

  • 检查并且调整数据库的配置如下
sql 复制代码
-- 1. 查看 binlog 是否开启
SHOW VARIABLES LIKE 'log_bin';
-- 应该显示 ON
​
-- 2. 查看 binlog 格式
SHOW VARIABLES LIKE 'binlog_format';
-- 应该显示 ROW
​
-- 3. 查看 server_id
SHOW VARIABLES LIKE 'server_id';
-- 应该显示 1
​
-- 4. 查看 binlog 是否生效
SHOW MASTER STATUS;
-- 应该显示当前的 binlog 文件和位置
​
-- 5. 查看所有 binlog 相关配置
SHOW VARIABLES LIKE '%binlog%';
  • 从GIT 上找到canal下载包地址,我这里用的是1.1.6

    复制代码
    https://github.com/alibaba/canal/releases
    Assets 里的文件列表说明
    文件名 说明 是否需要下载
    canal.adapter-1.1.6.tar.gz Canal Adapter 的核心程序包(你正在用的) ✅ 如果你要用 Adapter,必须下载这个
    canal.admin-1.1.6.tar.gz Canal Admin(Web 管理控制台) ❌ 除非你要用网页管理 Canal,否则不需要
    canal.deployer-1.1.6.tar.gz Canal Deployer(Canal Server 服务端) ✅但 Canal 整体架构需要它,用来连接MYsql
    canal.example-1.1.6.tar.gz 官方示例项目(含配置、SQL、测试数据) ❌ 一般开发者才需要
    Source code (zip) 源码压缩包(ZIP 格式) ❌ 一般开发者才需要
    Source code (tar.gz) 源码压缩包(tar.gz 格式) ❌ 一般开发者才需要
  • 修改配置

ES\canal.deployer-1.1.6\conf\example\instance.properties

bash 复制代码
canal.instance.master.address = 47.156.113.82:31218
canal.instance.dbUsername = canal
canal.instance.dbPassword = canal
canal.instance.name=example
canal.instance.connectionCharset = UTF-8
canal.instance.gtidon = false
canal.instance.tsdb.enable = true
canal.instance.get.ddl.isolation = false
canal.instance.parser.ddl.isolation = false
canal.instance.parser.parallel = false
​
canal.instance.filter.regex = .*\\..* 所有的库和表
canal.instance.network.soTimeout = 600
canal.instance.detecting.enable = true
canal.instance.detecting.interval.time = 1
canal.instance.binlog.format = ROW
canal.instance.binlog.image = FULL

说明: 这是 Canal Server 用来:

  • 连接 MySQL

  • 拉取 binlog

  • 解析 binlog

  • 控制同步行为

其中instance 名称(非常重要)比如adapter配置中

bash 复制代码
instance: example
destination: example

不一致 → Adapter 拿不到数据 / NPE / 无日志

其他的不用修改,然后直接启动canal 服务就可以了

看到这里就启动成功了,

你要配置canal.adapter-1.1.6.tar.gz这里面的文件了,首先解压到和.canal.deployer同级目录下(无所谓其实)

同样在conf中书写配置application.yml,注意1.1.6版本的配置写法如下

php 复制代码
server:
  port: 8081   # Canal Adapter 服务端口(HTTP接口/监控用)
​
spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss   # JSON 序列化日期格式
    time-zone: GMT+8                  # 时区(中国时间)
    default-property-inclusion: non_null  # 不序列化 null 字段
​
# 数据源配置(Spring 层使用)
spring.datasource:
  defaultDS:
    url: jdbc:mysql://47.116.153.12:31218/go?useUnicode=true&characterEncoding=UTF-8&useSSL=false
    username: canal     # MySQL 用户名(供 canal 使用)
    password: canal     # MySQL 密码
    driver-class-name: com.mysql.jdbc.Driver  # MySQL 驱动(旧版驱动)
​
# Canal 适配器核心配置
canal.conf:
  canal.client.adapter:
    dateFormat: yyyy-MM-dd HH:mm:ss  # canal 传输数据的时间格式
​
  mode: tcp          # canal 通信模式:tcp / kafka / rocketMQ / rabbitMQ
  flatMessage: true  # 是否使用扁平结构数据(推荐 true,方便 ES 写入)
  syncBatchSize: 1000  # 每批同步最大条数
  retries: 0         # 失败重试次数
  timeout:           # 超时时间(这里为空,默认值生效)
  accessKey:         # MQ/云环境访问 key(可选)
  secretKey:         # MQ/云环境 secret(可选)
​
  consumerProperties:
    # canal tcp 方式消费配置
    canal.tcp.server.host: 127.0.0.1:11111  # canal server 地址
    canal.tcp.batch.size: 500               # 每次拉取 binlog 数量
    canal.tcp.username:                     # canal 用户名(如果开启认证)
    canal.tcp.password:                     # canal 密码
​
  # =========================
  # 数据源配置(canal 监听的 MySQL)
  # =========================
  srcDataSources:
    defaultDS:
      url: jdbc:mysql://47.116.153.12:31218/go?useUnicode=true&characterEncoding=UTF-8&useSSL=false
      username: canal   # MySQL 账号
      password: canal   # MySQL 密码
      driver-class-name: com.mysql.jdbc.Driver
​
  # =========================
  # 适配器配置(重点:同步目标)
  # =========================
  canalAdapters:
    - instance: example   # canal instance 名称(必须和 canal-server 配置一致)
      groups:
        - groupId: g1     # 逻辑分组(可以多个同步任务)
​
          outerAdapters:
            - name: es7    # 输出到 Elasticsearch 7
              key: esKey   # adapter 标识 key(可随便定义)
              hosts: http://127.0.0.1:9200  # ES 地址
​
              properties:
                mode: rest   # 写 ES 模式:rest(推荐)/ transport(已废弃趋势)
                # security.auth: user:pass  # ES 开启认证时使用
                cluster.name: docker-cluster  # ES 集群名称(docker 默认)

配置解释都在参数中了,下面开始配置映射也就是表结构,同样在conf 文件中 es7

比如我这里配置了一个药材表herbs.yml

php 复制代码
dataSourceKey: defaultDS
outerAdapterKey: esKey
destination: example
groupId: g1
esMapping:
  _index: herbs
  _type: _doc
  _id: herb_id   
  upsert: true
​
  sql: "SELECT h.herb_id, h.common_name, h.scientific_name, h.other_names, h.properties, h.tastes, h.efficacy, h.image_url, h.origin, h.type, h.medicinal_smell_id, h.character_id, h.toxicity_id, h.book_id, h.pinyin, h.is_show, h.created_at, h.updated_at FROM herbs h"
​
  commitBatch: 1000
  dateFormat: yyyy-MM-dd HH:mm:ss

这个时候正常情况下启动

php 复制代码
rm logs/adapter/adapter.log &&   ./bin/stop.sh && ./bin/startup.sh   

去日志里面查看

出现succeed就是成功了

因为binlog是增量日志,有可能你需要做一次全量同步这个时候只需要访问

sql 复制代码
 curl -X POST http://127.0.0.1:8081/etl/es7/herbs.yml        

你就会看到下面的结果,如果原表数据量大,你可以选择分页,这个要去修改你的映射文件就行 这个时候es已经有了mysql中的数据了

接下来:修改binlog测试一下

我用sql 调整了一行信息,这里面的信息会立刻显示出来

再来检查ES中的

注意

复制代码
mysql8.2 adapter需要换库里面的包,我这里用的是
mysql-connector-j-8.3.0.jar
复制代码
报空指针错误一般是参数配置文件,删除不需要的参数就行,
另外如果版本不对,参数配置的全对也可能会出现空指针的错误
相关推荐
zmsofts2 小时前
java面试必问14:MySQL 索引类型:从基础到优化,面试官给你点赞
java·mysql·面试
JackSparrow4142 小时前
使用Elasticsearch代替数据库like以加快查询的各种技术方案+实现细节
大数据·clickhouse·elk·elasticsearch·搜索引擎·postgresql·全文检索
iNgs IMAC2 小时前
MySQL无法连接到本地localhost的解决办法2024.11.8
数据库·mysql·adb
tIzE TERV2 小时前
mysql数据被误删的恢复方案
数据库·mysql
eRTE XFUN2 小时前
mysql用户名怎么看
数据库·mysql
LDG_AGI2 小时前
【搜索引擎】Elasticsearch(五):prefix前缀匹配方法大全(包含search_as_you_type等6种解法)
人工智能·深度学习·算法·elasticsearch·搜索引擎
geBR OTTE2 小时前
mysql重置root密码(适用于5.7和8.0)
数据库·mysql·adb
Dxy12393102162 小时前
Elasticsearch 8 如何进行二维矩阵向量搜索
大数据·elasticsearch·矩阵