1. Canal简介

官方文档: https://github.com/alibaba/canal/wiki/简介

早期,阿里巴巴B2B公司因为存在杭州和美国双机房部署,存在跨机房同步的业务需求。早期的数据库同步业务,主要是基于trigger的方式获取增量变更,不过从2010年开始,阿里系公司开始逐步的尝试基于数据库的日志解析获取增量变更进行同步,由此衍生出了增量订阅&消费的业务,从此开启了一段新纪元,也就是Canal,翻译为管道的意思

工作原理

官网截图

先简单了解一下关于Mysql,master和slave的同步机制:

  1. master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events,可以通过show binlog events进行查看);需要手动打开,master在更新数据时,会同步操作日志文件,会有性能方面的影响,如果没有同步需要,关闭即可
  2. slave将master的binary log events拷贝到它的中继日志(relay log);
  3. slave重做中继日志中的事件,将改变反映它自己的数据。

详细信息可以参考:

以上是mysql主从备份的简单了解,以下是Canal的工作原理:

  1. canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议
  2. mysql master收到dump请求,开始推送binary log给slave(也就是canal)
  3. canal解析binary log对象(原始为byte流)
  4. canal将数据推送给指定的目标位置,并封装为对象的形式操作

2. Canal服务端搭建

2.1 部署Mysql

Mysql的搭建我这里就不说了,搭建完毕后,需要修改一些信息:

修改Mysql配置文件(我是在windows下,默认文件夹是C:\ProgramData\MySQL\MySQL Server 5.7\my.ini,需要打开隐藏目录):

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

创建Canal连接的账号,并赋予slave的权限:

CREATE USER canal IDENTIFIED BY 'canal';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
-- GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%' ;
FLUSH PRIVILEGES;

然后重启mysql服务即可

可以使用如下命令查看是否打开binlog模式:

show variables like 'log_bin';

查看binlog日志文件列表:

show binary logs

2.2 Canal服务搭建

下载canal包: https://github.com/alibaba/canal/releases ,我下载的是 1.1.5 版本, canal.deployer-1.1.5.tar.gz

解压完毕后, 修改conf/example/instance.properties 配置文件,如下:


# enable gtid use true/false
canal.instance.gtidon=false # 数据库地址
canal.instance.master.address=127.0.0.1:3306
#执行binlog文件
canal.instance.master.journal.name=mysql-bin.000001
#起始位置.跳过Mysql初始的一部分
canal.instance.master.position=154
canal.instance.master.timestamp=
canal.instance.master.gtid= # rds oss binlog
canal.instance.rds.accesskey=
canal.instance.rds.secretkey=
canal.instance.rds.instanceId= # table meta tsdb info
canal.instance.tsdb.enable=true # 数据库账号密码
canal.instance.dbUsername=canal
canal.instance.dbPassword=canal
canal.instance.connectionCharset = UTF-8
# enable druid Decrypt database password
canal.instance.enableDruid=false # 指定同步的表名 这里是全部
canal.instance.filter.regex=.*\\..*
# table black regex
canal.instance.filter.black.regex=mysql\\.slave_.* # mq config
canal.mq.topic=example
#canal.mq.dynamicTopic=mytest1.user,mytest2\\..*,.*\\..*
canal.mq.partition=0

然后执行bin目录下对应操作系统的启动脚本即可:

这样就启动成功了

3. 客户端搭建

创建客户端连接Canal服务

创建maven项目,导入依赖:

    <dependencies>
<dependency>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal.client</artifactId>
<version>1.1.5</version>
</dependency>
<dependency>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal.protocol</artifactId>
<version>1.1.5</version>
</dependency>
</dependencies>

客户端代码:

class SimpleCanalClientExample {

    public static void main(String args[]) {
// 创建链接
CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress(AddressUtils.getHostIp(),
11111), "example", "root", "root");
int batchSize = 1000;
int emptyCount = 0;
try {
connector.connect();
connector.subscribe(".*\\..*");
connector.rollback();
int totalEmptyCount = 120;
while (emptyCount < totalEmptyCount) {
// 获取指定数量的数据
Message message = connector.getWithoutAck(batchSize);
long batchId = message.getId();
int size = message.getEntries().size();
if (batchId == -1 || size == 0) {
emptyCount++;
System.out.println("empty count : " + emptyCount);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
} else {
emptyCount = 0;
// System.out.printf("message[batchId=%s,size=%s] \n", batchId, size);
printEntry(message.getEntries());
} connector.ack(batchId); // 提交确认
// connector.rollback(batchId); // 处理失败, 回滚数据
} System.out.println("empty too many times, exit");
} finally {
connector.disconnect();
}
} private static void printEntry(List<CanalEntry.Entry> entrys) {
for (CanalEntry.Entry entry : entrys) {
//如果是事务开启关闭时间则跳过
if (entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONBEGIN || entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONEND) {
continue;
} CanalEntry.RowChange rowChage = null;
try {
rowChage = CanalEntry.RowChange.parseFrom(entry.getStoreValue());
} catch (Exception e) {
throw new RuntimeException("ERROR ## parser of eromanga-event has an error , data:" + entry.toString(),
e);
} CanalEntry.EventType eventType = rowChage.getEventType();
System.out.println(String.format("================&gt; binlog[%s:%s] , name[%s,%s] , eventType : %s",
entry.getHeader().getLogfileName(), entry.getHeader().getLogfileOffset(),
entry.getHeader().getSchemaName(), entry.getHeader().getTableName(),
eventType)); for (CanalEntry.RowData rowData : rowChage.getRowDatasList()) {
if (eventType == CanalEntry.EventType.DELETE) {
printColumn(rowData.getBeforeColumnsList());
} else if (eventType == CanalEntry.EventType.INSERT) {
printColumn(rowData.getAfterColumnsList());
} else {
System.out.println("-------&gt; before");
printColumn(rowData.getBeforeColumnsList());
System.out.println("-------&gt; after");
printColumn(rowData.getAfterColumnsList());
}
}
}
} private static void printColumn(List<CanalEntry.Column> columns) {
for (CanalEntry.Column column : columns) {
System.out.println(column.getName() + " : " + column.getValue() + " update=" + column.getUpdated());
}
} }

当我们操作数据库时,客户端则可以获取到事件的发生:

empty count : 1
empty count : 2
empty count : 3
empty count : 4
empty count : 5
empty count : 6
empty count : 7
empty count : 8
empty count : 9
empty count : 10
empty count : 11
empty count : 12
empty count : 13
empty count : 14
================&gt; binlog[mysql-bin.000001:1893] , name[test,aa_test] , eventType : CREATE
empty count : 1
empty count : 2
empty count : 3
empty count : 4
empty count : 5
empty count : 6
empty count : 7
empty count : 8
empty count : 9
empty count : 10
empty count : 11
empty count : 12
empty count : 13
empty count : 14
empty count : 15
empty count : 16
empty count : 17
empty count : 18
================&gt; binlog[mysql-bin.000001:2698] , name[test,aa_test] , eventType : INSERT
id : 1111110946 update=true
status : 1 update=true
orderId : 1 update=true
orderProductId : 1 update=true
stanId : 1 update=true
quantity : 1 update=true
paymentDate : 2021-07-07 14:07:23 update=true
warehouse : 1 update=true
pid : 1 update=true
customerId : 1 update=true
type : 1 update=true
empty count : 1
empty count : 2
empty count : 3
empty count : 4

如上日志显示, 创建表和向中插入一条数据的时间都被记录,并打印出插入的数据

1. Canal入门的更多相关文章

  1. canal入门Demo

    关于canal具体的原理,以及应用场景,可以参考开发文档:https://github.com/alibaba/canal 下面给出canal的入门Demo (一)部署canal服务器 可以参考官方文 ...

  2. (1)Canal入门

    1.前言 在我们系统开发过程中,根据业务场景很多数据库数据并不会直接给用户访问的,需要同步保存到ElasticSearch.Redis等存储应用当中(例如最常见的是搜索页面的ElasticSearch ...

  3. canal 入门(基于docker)

    第一步:安装MySQL:(可以参考:https://my.oschina.net/amhuman/blog/1941540) 命令: sudo docker run -it -d --restart ...

  4. canal 入门

    参考文章:Canal - 安装   https://www.aliyun.com/jiaocheng/1131288.html?spm=5176.100033.2.7.7b422237XAirIe 前 ...

  5. canal入门使用

    1.下载canal安装包: 地址:https://github.com/alibaba/canal/releases 图例: 2.将下载好的安装包复制到Linux,解压 3.修改配置文件 vi con ...

  6. Canal入门

    配置mysql 1.mysql开启binlog mysql默认没有开启binlog,修改mysql的my.cnf文件,添加如下配置,注意binlog-format必须为row,因为binlog如果为S ...

  7. 数据的异构实战(一) 基于canal进行日志的订阅和转换

    什么是数据的异构处理.简单说就是为了满足我们业务的扩展性,将数据从某种特定的格式转换到新的数据格式中来. 为什么会有这种需求出现呢? 传统的企业中,主要都是将数据存储在了关系型数据库中,例如说MySQ ...

  8. 使用canal分析binlog(一) 入门

    canal介绍 canal是应阿里巴巴存在杭州和美国的双机房部署,存在跨机房同步的业务需求而提出的.早期,阿里巴巴B2B公司因为存在杭州和美国双机房部署,存在跨机房同步的业务需求.不过早期的数据库同步 ...

  9. canal 结合 kafka 入门

    1.kafka的安装: 略 2.cannal  配置 使用卡夫卡: 修改  /home/admin/canal-server/conf/canal.properties 2.1 修改canal.ser ...

  10. 「从零单排canal 01」 canal 10分钟入门(基于1.1.4版本)

    1.简介 canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据 订阅 和 消费.应该是阿里云DTS(Data Transfer Servi ...

随机推荐

  1. ElasticSearch-索引库、文档操作

    1.elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大功能,可以帮助我们从海量数据中快速找到需要的内容 2.elasticsearch和lucen ...

  2. Intel 4工艺太难了!酷睿Ultra终于突破5GHz

    无论是14nm还是10nm,Intel这些年的新工艺都有一个通性:刚诞生的时候性能平平,高频率都上不去,只能用于笔记本移动端(分别对应5代酷睿.10代酷睿),后期才不断成熟,比如到了13代酷睿就达到史 ...

  3. 【Linux】常用基本指令大汇总系列(篇一)【超详细的图解保姆教程】

    常用基本指令大汇总系列(篇一) 大家好,欢迎大家来到我的博客.从今天开始,博主就要开启一个全新的系列了!Linux操作系统常用基本指令汇总系列,当大家按顺序学完这个系列,在Linux上编写基本的C语言 ...

  4. 【Linux】虚拟机太卡咋办?用云服务器Xshell配置Vmware虚拟机【技能篇】

    [Linux]用云服务器Xshell配置Vmware虚拟机[技能篇] 强烈建议本篇收藏后再食用~ 文章目录 Xshell下载 配置Vmware 尾声 平时我们使用虚拟机,可能最烦人的问题就是卡顿了.今 ...

  5. npm script 详解,tsc && electron . 直接编译后 运行,非常方便

    最终平时只需要用这个方法就可以了: tsc && electron . ======================================================== ...

  6. Hadoop组件兼容性

    (1)HBase和Hadoop.zookeeper.JDK兼容版本 参考网址: https://hbase.apache.org/book.html 1)JDK和Hbase的兼容版本  对于JDK,最 ...

  7. MySQL 8 查询优化新工具 Explain Analyze

    1. Explain Analyze 介绍 Explain 是我们常用的查询分析工具,可以对查询语句的执行方式进行评估,给出很多有用的线索.但他仅仅是评估,不是实际的执行情况,比如结果中的 rows, ...

  8. NOI 2021 补全记录

    来补题了昂. D1T1 轻重边 对于原树进行重链剖分,使用一颗线段树维护每一条重边是否时"重边",然后对于轻边,在父亲出维护最后一次通过 \(1\) 操作清空"重边&qu ...

  9. 从零开始的微信小程序入门教程(三),有趣且好玩的数据绑定

    壹 ❀ 引 我在从零开始的微信小程序入门教程(二),初识WXML与WXSS一文中简单介绍了小程序组件与小程序样式相关概念,在了解这两者之后,其实我们已经可以搭建出简单的静态页面,与书写HTML页面一样 ...

  10. NC16679 [NOIP2003]神经网络

    题目链接 题目 题目描述 人工神经网络(Artificial Neural Network)是一种新兴的具有自我学习能力的计算系统,在模式识别.函数逼近及贷款风险评估等诸多领域有广泛的应用.对神经网络 ...