0. 原理
canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送 dump 协议
MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
canal 解析 binary log 对象(原始为 byte 流)
1. docker部署相关容器
elasticsearch、mysql、canal-server、kibana
注意elasticsearch的数据卷参数、elasticsearch和kibana的网络参数
参考之前文章:juejin.cn/post/684490…
2. 创建用户,不要使用mysql默认的root
CREATE USER canal IDENTIFIED BY 'canal';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
FLUSH PRIVILEGES;
3. mysql elasticsearch canal-server应该都在一个网络中
在上面的文章中elasticsearch和kibana已经在同一个网络中,将mysql和canal-server也加入进去
## mysql
sudo docker run -d --name mysql -v /home/ubuntu/docker/mysql/volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 --network=elasticsearch-kibana mysql
## canal-server,注意用户名和密码是刚刚创建的canal/canal
sudo docker run -e canal.instance.master.address=192.168.0.106:3306 \
-e canal.instance.dbUsername=canal \
-e canal.instance.dbPassword=canal \
-e canal.instance.connectionCharset=UTF-8 \
-e canal.instance.tsdb.enable=true \
-e canal.instance.gtidon=false \
-e canal.instance.filter.regex=.*\\..* -d -p 11111:11111 --name canal-server --network=elasticsearch-kibana canal/canal-server
inspect命令可以看到已经加入同一个网络
ubuntu@ubuntuserver:~$ sudo docker inspect 0ca051d632b1393a25caf8 | grep NetworkMode
"NetworkMode": "elasticsearch-kibana",
4. 启动canal-adapter
1. 下载
https://github.com/alibaba/canal.git
我这里下载的是1.1.3
2. idea导入client-adapter项目
找到root模块,install一下,否则直接运行会报错: Load canal adapter: xx failed
注意,如果你的docker部署的mysql是8.x版本,那么需要把launcher模块中的pom文件,mysql依赖的版本号注释掉,这样就会自动依赖mysql connector 8.x版本,低版本的驱动是连不上高版本的mysql的。
3. 修改launcher模块的application.yml
## 这里修改成自己的canal-server地址
canalServerHost: 192.168.0.106:11111
## 这里修改成自己的mysql相关信息
canal.conf:
mode: tcp # kafka rocketMQ
canalServerHost: 192.168.0.106:11111
batchSize: 500
syncBatchSize: 1000
retries: 0
timeout:
accessKey:
secretKey:
srcDataSources:
defaultDS:
url: jdbc:mysql://192.168.0.106:3306/chinsblog?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false
username: canal
password: canal
canalAdapters:
- instance: example # canal instance Name or mq topic name
groups:
- groupId: g1
outerAdapters:
- name: logger
- name: es
hosts: 192.168.0.106:9300
properties:
cluster.name: docker-cluster
4. 创建数据库表和elasticsearch索引
我这里是用我项目里的entity,然后通过@test方法实现的。
(我的项目是一个前后端分离的vue + springboot实现的博客项目,以后打算梳理和重构一下,写成文章,方便自己复盘)
## github:
https://github.com/toyranger/chins-blog-backend.git
https://github.com/toyranger/chins-blog-frontend.git
## entity
@Document(indexName = "chinsblog_article", type = "article")
@Data
public class Article {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private String title;
private String content;
private String date;
private int views;
private int comments;
private int thumbs;
}
## test
@Test
public void createArticleIndex() {
List<Article> articles = articleMapper.selectList(null);
for (Article article : articles) {
articleESRepository.index(article);
}
}
所以现在的kibana上面可以看到我elasticsearch里的索引和数据
5. 创建同步配置文件
在resources目录下的yml文件都可以。
dataSourceKey: defaultDS
destination: example
groupId: g1
esMapping:
## index 和 type,和entity中的注解保持一致,即和elasticsearch中的mapping保持一致
_index: chinsblog_article
_type: article
_id: _id
upsert: true
# pk: id
## 注意这里的as _id,否则同步的时候会空指针,而且为什么同步过去的文档,没有id这个字段了???
sql: "SELECT a.id as _id, a.title, a.content, a.date, a.views, a.comments, a.thumbs FROM chinsblog.article a"
# objFields:
# _labels: array:;
# etlCondition: "where a.c_time>='{0}'"
commitBatch: 3000
6. 运行launcher的main方法,启动canal-adapter
可以看到,已经连接成功
尝试update和insert表数据,可以看到同步过程以及结果,同时kibana中可以看到同步之后的elasticsearch数据:
kibana: