数据同步工具Canal入门

441 阅读3分钟

一、简介

Canal是阿里开源的数据同步工具,使用java开发。主要支持Mysql。

二、使用场景

2.1. 数据同步。--推荐

Canal可以帮助用户进行多种数据同步操作。如实时同步MySql数据到Elasticsearch、Redis等数据存储介质中。

2.2. 数据分析和挖掘 --推荐

Canal可以将Mysql增量数据投递到Kafka等消息队列中,为数据分析和挖掘提供数据来源。

2.3. 数据库实时监控。

Canal可以实时监控MySql的更新操作,对于敏感数据的修改可以及时通知相关人员。

2.4. 数据库备份。

Canal可以将MySql主库上的数据增量日志复制到备份库上,实现数据备份。

2.5. 数据集成。

Canal可以将多个MySql数据库中的数据进行集成,为数据处理提供更加高效可靠的解决方案。

2.6. 数据迁移。

Canal可以协助完成MySql数据库的版本升级及数据迁移任务。 当数据发生变动时,将数据迁移到高版本的数据库中。

三、Canal工作原理

3.1 Mysql的主从同步原理

  1. master将增、删、改操作记录到binary log中。
  2. slave开启一个I/O thread,读取binary log,存入到中继日志relay log中。
  3. slave开启一个sql thread,读取relay log的数据,重放relay log操作,将变更数据同步到最新。

3.2 MySql Binlog日志

记录了所有的DDL和DML语句,以事件形式记录。Mysql默认情况下不开启binlog。 Binlog的分类:STATEMENT\ROW\MIXED。

分类介绍优点缺点
STATEMENT语句级别,记录每一次写操作的语句。节省空间。可能造成数据不一致。如update tt set create_date = now()。由于执行时间不同,产生的数据就不同。
ROW行级。记录每次操作后每行记录的变化。保持数据的绝对一致性。只记录执行后的结果。占用较大空间。比如批量更新1万条数据,STATEMENT只需要记录一条语句,但是ROW需要保存一万条记录。
MIXED两种方式的混合。节省了空间,同时保证了一定的一致性。会有极个别情况造成不一致。

Canal想做监控分析,选择ROW比较合适。

3.3 Canal工作原理

  1. Canal将自己伪装成Mysql slave,向Mysql master发送dump协议。
  2. Mysql master收到dump请求,开始推送binary log给slave(Canal)。
  3. Canal接收并解析Binlog日志,得到变更的数据,执行后续逻辑。

dzy18Q5adM.jpg

四、springboot集成Canal编程

  1. maven配置
<dependency>
    <groupId>top.javatool</groupId>
    <artifactId>canal-spring-boot-starter</artifactId>
    <version>1.2.1-RELEASE</version>
</dependency>
  1. application.yml文件配置
canal:
  server: 127.0.0.1:1111
  destination: example
spring:
  application:
    name: spring-boot-demo
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: url
    username: name
    password: pwd
  1. 定义实体类
public class UserEntity {

    private String name;

    private Integer age;
}
  1. 定义一个Handler类,监控到增删改的数据
@Component
@CanalTable("user")
public class UserHandler implements EntryHandler<UserEntity> {
    @Override
    public void insert(UserEntity userEntity) {
        System.out.println("监控到insert的数据");
    }

    @Override
    public void update(UserEntity before, UserEntity after) {
        System.out.println("监控到update的数据");
    }

    @Override
    public void delete(UserEntity userEntity) {
        System.out.println("监控到delete的数据");
    }
}