一、简介
canal主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费。
二、工作原理
canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送 dump 协议MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )canal 解析 binary log 对象(原始为 byte 流)
三、基于canal实现mysql和es增量数据同步
3.1 基于canalServer和canalAdapter的方式进行数据同步
worker:数据全量同步组件
canalServer:接收binlog信息
canalAdapter:canalServer和elasticSearch适配
canal作为增量数据同步的工具,同时对不同数据源做了适配,canalAdapter目前默认支持的数据源有:Hbase,ElasticSearch和RDB(关系型数据库)。
通过canalServer和canalAdapter的一些配置(各个中间件配置信息请参考官方文档),无需代码开发就能实现不同数据源之间的同步。
但是用这种方式如果数据量大,可能会产生数据积压,有数据丢失的风险。
3.2基于mq和canalClient的方式进行数据同步
canal 1.1.1版本之后, 默认支持将canalServer接收到的binlog数据直接投递到MQ, 目前默认支持的MQ系统有:kafka和RocketMQ。
我们需要在应用中开发canalClient,esClient和mqConsumer组件
canalClient:将消息解析并封装成对应实体
esClient:elasticSearch基本操作
mqConsumer:消费消息,通过canalClient将消息解析成对应的实体对象,通过esClient将对象写入到elasticSearch集群。
canalClient的关键代码解析Message中的Entries,代码如下:
private static void printEntry(List entrys) {
for (Entry entry : entrys) {
if (entry.getEntryType() == EntryType.TRANSACTIONBEGIN || entry.getEntryType() == EntryType.TRANSACTIONEND) {
continue;
}
RowChange rowChage;
try {
rowChage = RowChange.parseFrom(entry.getStoreValue());
} catch (Exception e) {
throw new RuntimeException("ERROR ## parser of eromanga-event has an error , data:" + entry.toString(), e);
}
//获取操作类型:insert/update/delete类型
EventType eventType = rowChage.getEventType();
//打印Header信息
System.out.println(String.format("================》;
binlog[%s:%s] , name[%s,%s] , eventType : %s",
entry.getHeader().getLogfileName(), entry.getHeader().getLogfileOffset(),
entry.getHeader().getSchemaName(), entry.getHeader().getTableName(),
eventType));
//判断是否是DDL语句
if (rowChage.getIsDdl()) {
System.out.println("================》;
isDdl: true,sql:" + rowChage.getSql());
}
//获取RowChange对象里的每一行数据,打印出来
for (RowData rowData : rowChage.getRowDatasList()) {
//如果是删除语句
if (eventType == EventType.DELETE) {
printColumn(rowData.getBeforeColumnsList());
//如果是新增语句
} else if (eventType == EventType.INSERT) {
printColumn(rowData.getAfterColumnsList());
//如果是更新的语句
} else {
//变更前的数据
printColumn(rowData.getBeforeColumnsList());
//变更后的数据
printColumn(rowData.getAfterColumnsList());
}
}
}
}
四、小结
canal只适合做增量数据同步,全量数据同步需要采用其他的方式来实现。
【技术|基于canal实现mysql和es增量数据同步】?
推荐阅读
- 《mongodb经典入门》|四.MongoDB入门-Java操作MongoDB
- 《mongodb经典入门》|五.MongoDB入门-SpringData操作MongoDB
- elasticSearch|canal1.15 增量同步 mysql5.7 数据到ElasticSearch7.14.0
- elasticsearch|通过canal将MySQL数据同步到Elasticsearch
- elasticsearch|使用canal同步MySQL数据到Elasticsearch(ES)
- 程序员|普通二本的辛酸Java面试之路,实战篇
- 程序员|【深度思考】普通二本的辛酸Java面试之路,含答案解析
- 大厂面试系列|我的秋招 | 大厂上岸经验一(末流二本)
- 图解 Docker 架构,还有谁不会()