liunx下通过Canal将MySQL数据同步到Elasticsearch
一、canal背景信息
Canal是Github中开源的ETL(Extract Transform Load)软件
canal,译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费
当前的 canal 支持源端 MySQL 版本包括 5.1.x , 5.5.x , 5.6.x , 5.7.x , 8.0.x
MySQL master 将数据变更写入二进制日志( binary log, 其中记录叫做二进制日志事件binary log events,可以通过 show binlog events 进行查看)
MySQL slave 将 master 的 binary log events 拷贝到它的中继日志(relay log)
MySQL slave 重放 relay log 中事件,将数据变更反映它自己的数据
canal 工作原理:
1.1 canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
1.2 MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
1.3 canal 解析 binary log 对象(原始为 byte 流)
二、mysql相关配置
1、由于canal是通过订阅MySQL的binlog来实现数据同步的,所以我们需要开启MySQL的binlog写入功能,并设置binlog-format
为ROW模式,我的配置文件为/etc/my.cnf,改为如下内容即可
[mysqld]
log-bin=mall-mysql-bin #开启二进制日志功能 或者 log_bin=on #开启bin-log日志
binlog_format=row #设置使用的二进制日志格式(mixed,statement,row)
server_id=101 #设置server_id,同一局域网中需要唯一 , 注意server_id不要和canal的slaveId重复
binlog-ignore-db=mysql #指定不需要同步的数据库名称
binlog_cache_size=1M #设置二进制日志使用内存大小(事务)
expire_logs-days=7 #二进制日志过程清理时间。默认为0,表示不自动清理
slave_skip_errors=1062 #跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断 #如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
symbolic-links = 0: #符号连接,如果设置为1,则mysql数据库和表里的数据支持储存在datadir目录之外的路径下,默认都是0(较新版本的mysql下默认是1)
pid-file=/usr/local/mysql/data/mysql.pid
log-error=/usr/local/mysql/data/mysql.log
socket=/var/lib/mysql/mysql.sock
datadir=/usr/local/mysql/data
log-bin=/usr/local/mysql/data/mysql-bin #设置logbin日志存放目录
2、配置完成后需要重新启动MySQL,重启成功后通过如下命令查看binlog是否启用
SHOW VARIABLES LIKE '%log_bin%';
3、再查看下MySQL的binlog模式
SHOW VARIABLES LIKE 'binlog_format';
4、接下来需要创建一个拥有从库权限的账号,用于订阅binlog,这里创建的账号为canal:canal
GREAT USER canal IDENTIFIED BY 'canal';
5、赋予canal用户权限
GRANT SELECT, INSERT,REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
FLUSH PRIVILEGES;
6、创建库和创建表
create database elasticsearch;
CREATE TABLE `es_test` (
`id` int NOT NULL AUTO_INCREMENT,
`count` text,
`name` text,
`color` text,
PRIMARY KEY (`id`)
)
三、canal的下载及使用
1、由于不同版本的MySQL、Elasticsearch和canal会有兼容性问题,下面介绍本文涉及到组件的版本
组件 | 端口 | 版本 |
---|---|---|
elasticsearch | 9200 | 7.13.2 结合openjdk11使用 |
kibana | 5601 | 7.13.2 结合openjdk11使用 |
mysql | 3306 | 8.0.20 结合openjdk11使用 |
canal-admin | 8089 | 1.16 结合openjdk11使用 |
canal-server | 11111 | 1.16 结合openjdk11使用 |
canal-adapter | 8081 | 1.16 结合openjdk11使用 |
2、下载canal的各个组件canal-server
、canal-adapter
、canal-admin
,下载地址:https://github.com/alibaba/canal/releases
3、canal各个组件功能介绍
canal-server(canal-deploy):可以直接监听MySQL的binlog,把自己伪装成MySQL的从库,只负责接收数据,并不做处理。
canal-adapter:相当于canal的客户端,会从canal-server中获取数据,然后对数据进行同步,可以同步到MySQL、Elasticsearch和HBase等存储中去。
canal-admin:为canal提供整体配置管理、节点运维等面向运维的功能,提供相对友好的WebUI操作界面,方便更多用户快速和安全的操作。
4、canal-server的使用
将我们下载好的压缩包canal.deployer-1.1.6-SNAPSHOT.tar.gz
上传到Linux服务器,然后解压到指定目录/home/server
,可使用如下命令解压
tar xvzf canal.deployer-1.1.5-SNAPSHOT.tar.gz -C /home/server/
canal-server工作目录如下
修改conf/example/instance.properties文件,主要注意以下几处:
canal.instance.master.address=127.0.0.1:3306 #mysql主数据库地址
# username/password
canal.instance.dbUsername=canal
canal.instance.dbPassword=canal
canal.instance.connectionCharset = UTF-8
canal.instance.filter.regex=.*\\..* #需要订阅binlog的表过滤正则表达式
启动canal-server并查看日志
./bin/startup.sh 或者: sh bin/startup.sh
cat logs/canal/canal.log 或者:tail -f logs/example/example.log
5、canal-adapter的使用
将我们下载好的压缩包canal.adapter-1.1.5-SNAPSHOT.tar.gz
上传到Linux服务器,然后解压到指定目录/home/adpter
,解压完成后目录结构如下
修改配置文件conf/application.yml,按如下配置即可,可以注释不需要的配置,主要是修改canal-server配置、数据源配置和客户端适配器配置
#同步的数据库
srcDataSources:
defaultDS:
url: jdbc:mysql://192.**.**.**:3306/elasticsearch?useUnicode=true&useSSL=true&allowMultiQueries=true&verifyServerCertificate=false&serverTimezone=Asia/Shanghai
username: canal
password: canal
canalAdapters: # 适配器列表
- instance: example #与canal-server中canal.properties的实例名相同
groups:
- groupId: g1 #与下面适配器对应
outerAdapters:
- name: es7 #es配置,这里使用9200通信 也就是rest模式
key: es7Key #对应es的适配器key
hosts: http://192.**.**.**:9200 # hosts使用的是es的9200端口
properties:
mode: rest # or rest
security.auth: usernama:password
cluster.name: elasticsearch #es的集群名称
添加配置文件canal-adapter/conf/es7/es_test.yml
,用于配置MySQL中的表与Elasticsearch中索引的映射关系
dataSourceKey: defaultDS
outerAdapterKey: es7Key # 对应application.yml中es配置的key
destination: example #和上面配置文件对应
groupId: g1 #和配置文件对应
esMapping:
_index: es_test #es索引名称
_id: id # 需要同步到Elasticsearch实例的文档的id,可自定义。本文使用_id, 如果不配置该项必须配置下面的pk项_id则会由es自动分配
# relations:
# customer_order:
# name: customer
sql: "select es.id, es.count, es.name,es.color from es_test es" #SQL语句,用来查询需要同步到Elasticsearch中的字段
# etlCondition: "where a.c_time>={}" #etl的条件参数
commitBatch: 200 # 批量提交的大小
启动Canal-adapter服务,并查看日志
./bin/startup.sh 或者: sh bin/startup.sh
cat logs/adapter/adapter.log 或者:tail -f logs/adapter/adapter.log
四、数据同步演示
经过上面的一系列步骤,canal的数据同步功能已经基本可以使用了,下面我们来演示下数据同步功能。
首先我们需要在Elasticsearch中创建索引,和MySQL中的product表相对应,直接在Kibana的Dev Tools中使用如下命令创建即可;
创建index :
PUT es_test
{
"settings": {
"index": {
"number_of_shards": "3", #主分片数,默认为1,索引分片对ES的查询性能有很大的影响,在应用环境,应该选择适合的分片大小。
"number_of_replicas": "0" #设置默认索引副本个数,默认为1个副本。此处的1个副本是指index.number_of_shards的一个完全拷贝;如果有5个主分片1个副本分片,即总分片数为10。
}
}
}
注意:可以在线修改副本分片数 number_of_replicas ,但主分片数 number_of_shards 不可以在线改
定义mappering,由于上面数据库字段类型为text,:
PUT es_test/_doc/_mapping
{
"properties": {
"color": {
"type": "keyword"
},
"count": {
"type": "keyword"
},
"name": {
"type": "keyword"
}
}
}
创建成功:
创建完成后查看索引结构:
在mysql数据库中插入一条数据:
INSERT INTO `elasticsearch`.`es_test` (`id`, `count`, `name`, `color`) VALUES (1, '99', '不知好歹', '黑色');
Elasticsearch在kibana中搜索下,发现数据已经同步了
GET es_test/_search
五、canal adpter常见启动报错
java.nio.ByteBuffer.clear()Ljava/nio/ByteBuffer;
解决:canal1.1.6 对应 jdk1.6,版本不对应
missing authentication credentials for REST request 401
五、canal adpter常见启动报错
java.nio.ByteBuffer.clear()Ljava/nio/ByteBuffer;
解决:canal1.1.6 对应 jdk1.6,版本不对应
missing authentication credentials for REST request 401
解决:/home/adpter/conf/application.yml 添加凭证:security.auth