Canal 实时同步数据MySQL到Elasticsearch

750 阅读6分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天,点击查看活动详情

前言

由于业务的增长,目前 MySQL 对于千万级数据量的查询性能相对比较差,为了适应后续业务数据的增长,提高搜索速度;我们在技术选型上采用了 Elasticsearch 来存储,原始数据还是存 MySQL,那么如何将 MySQL 的数据实时同步到 ElasticSearch。我们选择了目前业界比较常用的增量同步工具Canal。

1、概述

1.1 canal是什么

canal是阿里巴巴旗下的一款开源项目。基于数据库增量日志解析,提供增量数据订阅&消费,目前主要支持了MySQL。

1.1.1 数据库增量日志(binlog)

当我们对数据库进行数据操作(增删改)等操作时,mysql 如果开启 binlog ,会把当前的操作记录到 binlog 日志中,它就是相当于 mysql 的日志文件。

binlog有三种日志格式:

  • STATEMENT: 只记录修改的 sql 语句 ,不记录数据。无法恢复数据。
  • ROW : 不记录每一条SQL语句的上下文信息,仅需记录哪条数据被修改了,修改成了什么样子了
  • MIXED: STATEMENT + ROW

要进行数据同步一般使用 ROW 模式。

mysql的配置:

[mysqld]
log-bin=mysql-bin # 开启 binlog
binlog-format=ROW # 选择 ROW 模式
server_id=1 # 配置 MySQL replaction 需要定义,不要和 canal 的 slaveId 重复

1.2 需求背景

  • 当前数据存储在 ES 上,使用 Datax 每天凌晨进行全量同步,主要存在的问题是实时性不够。当业务中,比如有人之前受到“行政处罚”,那他来部门办理撤销后,想马上去办理其他业务的话,那么如果不及时同步这条数据信息,其他部门还查询得到他还未撤销该项数据,会导致数据不一致,业务延迟。所以,这个时候需要有个实时同步的工具及时同步更新数据。

2 canal的工作原理

2.1 mysql主从同步原理

  1. Master主库,启动Binlog机制,将变更数据写入Binlog文件;
  2. Slave(I/O thread),从Master主库拉取binlog日志,将它拷贝到Slave的中继日志(relay log)中;
  3. Slave(SQL thread),回放Binlog,更新从库数据;

其中 I/0 线程 接收binlog ,SQL 线程 执行变更

启用 binlog 注意点:

  1. Master主库一般会有多台Slave订阅,且Master主库要支持业务系统实时变更操作,服务器资源会有瓶颈;
  2. 需要同步的数据表一定要有主键;

2.2 canal工作原理

  1. canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
  2. MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
  3. canal 解析 binary log 对象(原始为 byte 流)

3 canal应用使用

目前使用 canal 有两个应用,1个 server 端,1个 client 端。使用版本最新版的 1.1.5, 当然 client 端也可以自己实现。

  • canal.deployer-1.1.5-SNAPSHOT = server 端
  • canal.adapter-1.1.5 client端
  • canal.admin-1.1.5 :canal server 配置的界面化操作,(后续提供,方便实施配置) 端口(8089)

3.1 实践

以下展示实践过程中,canal 的使用方式。

  • server 端连接 mysql,读取 binlog 日志,然后存储起来
  • client 端 消费 server 端的 binlog
  • 一个 server 配置了两个 canal 实例(instance),每个client 连接一个实例。
  • 每个实例模拟为 mysql 的 slave ,saveid 配置要不相同,都会拉取 Mysql 主节点的binlog

注意 Canal server 上的 一个 instance 只能一个 client 消费

3.2 server 和 client 端的交互

server 和 client 端 是 c/s 模式通信 ,server (netty)client(NIO 非阻塞异步I/0)

  1. canal server 启动后,没有 client 端,server 不会 mysql 拉取数据
  2. client 会主动发去拉取请求,服务端 模拟成 slave 去主库拉取 binlog
  3. 通常Canal客户端是一个死循环,这样客户端一直调用get方法,服务端也就会一直拉取binlog。

3.2.1 增量订阅/消费设计

  • subscribe:订阅需要哪些表或者库的binlog日志解析
  • get :批量获取 服务端的解析好的binlog 对象
  • rollback: 回滚上一次的get请求,重新获取数据。
  • ack:确认消费成功,通知服务端进行删除

3.3 canal server

  • Server 代表一个 canal 运行实例,对应于一个 jvm
  • instance 对应于一个数据队列

instance模块:

  • eventParser (数据源接入,模拟slave协议和master进行交互,协议解析)
  • eventSink (Parser和Store链接器,进行数据过滤,加工,分发的工作)
  • eventStore (数据存储)
  • metaManager (增量订阅&消费信息管理器)

  • Put : Sink模块进行数据存储的最后一次写入位置
  • Get : 数据订阅获取的最后一次提取位置
  • Ack : 数据消费成功的最后一次消费位置

4 canal的使用

目前 canal 在业务中使用场景,主要有两个,分别是进行数据同步,订阅数据变化,进行业务处理。

4.1 数据同步

  • 数据同步流程

4.1.1 MySQL 到 es 同步

使用 canal adapter 进行数据同步时,需要配置 源表到目标表的配置,主要是个 yml 文件,内容如下:

放置在 adapter目录下 conf/es6 下

当配置放入后,client就可以进行数据同步了。

当新增配置后,只需把配置文件放入配置文件上,client 端 后自动加载配置文件。

4.2 监控 MySQL 数据变化进行数据处理

  • 后端服务作为client监听数据库变更,然后将变更的数据写入MQ进行任务下发。

5 目前使用性能情况

这部分,主要是对目前使用 canal 进行大批量数据同步存在性能问题的情况,给大家做个输入。目前做的性能测试还是相当有限,后续如果要大范围使用,我个人认为还是得根据现场情况,进行更大数据量的同步测试。

5.1 增量同步测试

在目前,给予 canal 的地位就是进行增量同步,同步过程中,我们分为 MySQL 到 MySQL,MySQL 到 ES

5.1.1 mysql库到mysql库同步

数据量:65870

insertupdatedelete
mysql 从库有点快,飞快瞬间来不及看
canal 同步4分钟差不多3,4分钟之间4分钟

5.1.2 mysql 到 ES 的同步

数据量:65870

insertupdatedelete
Canal 入库10分钟以内10分钟左右5分钟

5.2 全量同步性能测试

canal 也提供了 全量同步的接口供外部调用,但是效率有待验证。目前我们还是维持全量同步使用 DataX

全量同步 语法

curl http://127.0.0.1:8081/etl/rdb/mytest_person2.yml -X POST -d "params=2018-10-21 00:00:00"

mysql 到 es

curl http://127.0.0.1:8081/etl/es6/elsearch/ES6_test.yml -X POST

查看相关库的总数据

curl http://127.0.0.1:8081/count/rdb/mytest_person2.yml

5.3 官方的性能测试报告

阅读来源

官网最好的学习资源: canal 官网