数据同步解决方案-canal

工作原理

canal 译意为水道,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费。

* MySQL主备复制原理
MySQL master 将数据变更写入二进制日志( binary log, 其中记录叫做二进制日志事件binary log events,可以通过 show binlog events 进行查看)
MySQL slave 将 master 的 binary log events 拷贝到它的中继日志(relay log)
MySQL slave 重放 relay log 中事件,将数据变更反映它自己的数据
* canal 工作原理
canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
canal 解析 binary log 对象(原始为 byte 流)

mysql开启binlog

1. 登录mysql,使用       show variables like 'log_bin';       命令查看是否已开启binlog

 2. 如果没有开启的话,则需要修改my.cnf文件指定binlog信息

# 当前数据库唯一编号
server-id=12345
# 二进制日志存储地址(mysql-bin是文件前缀)
log-bin=/var/lib/mysql/logs/mysql-bin
# binlog日志格式,mysql默认采用statement,canal建议使用ROW
binlog_format=ROW
# binlog过期清理时间
expire_logs_days=7
# binlog每个日志文件大小
max_binlog_size=100m
# binlog缓存大小
binlog_cache_size=4m
# 最大binlog缓存大小
max_binlog_cache_size=512m



这里指定了log-bin=/var/lib/mysql/logs目录,logs是手动创建出来的,且要   chmod -R 777 logs   赋予权限,否则mysql启动失败

 

3. 修改完成之后,重启mysqld的服务。

canal服务端安装

1. 下载地址
https://github.com/alibaba/canal/releases/tag/canal-1.0.24
2. 解压
mkdir canal && tar -zxvf canal.deployer-1.0.24.tar.gz -C canal
3. 修改pid (canal像一个从库去读取mysql数据,所以他们的id是不能冲突的,mysql的刚才改为12345了)
vim conf/canal.properties

 4. 配置数据库信息和监听规则

#################################################
## mysql的id
canal.instance.mysql.slaveId = 12345

# position info
canal.instance.master.address = 127.0.0.1:3306
canal.instance.master.journal.name =
canal.instance.master.position =
canal.instance.master.timestamp =

#canal.instance.standby.address = 
#canal.instance.standby.journal.name =
#canal.instance.standby.position = 
#canal.instance.standby.timestamp = 

# username/password
canal.instance.dbUsername = root
canal.instance.dbPassword = 123456
canal.instance.defaultDatabaseName =
canal.instance.connectionCharset = UTF-8


#所有库的所有表
#canal.instance.filter.regex = .*\\..*
#meiye库的system_user表
#canal.instance.filter.regex =meiye.system_user
#meiye 和 brm 的所有表
canal.instance.filter.regex =meiye.*,brm.*
# table black regex
canal.instance.filter.black.regex =

#################################################
~        
View Code

代码测试

1. 导入依赖
        <dependency>
            <groupId>com.xpand</groupId>
            <artifactId>starter-canal</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>



2. 配置canal地址信息
canal:
  client:
    instances:
      example:
        host: 192.168.200.100
        port: 11111
        batchSize: 1000



3. 启动类开启canal注解
@EnableCanalClient //声明当前的服务是canal的客户端


4. 测试代码

import com.alibaba.otter.canal.protocol.CanalEntry;
import com.xpand.starter.canal.annotation.*;
/**
 * mysql数据监听
 */
@CanalEventListener
public class CanalDataEventListener {

    /**
     * 监听新增事件
     * @param eventType 操作事件类型(新增)
     * @param rowData 发生变化的一行数据
     */
    @InsertListenPoint
    public void onEventInsert(CanalEntry.EventType eventType, CanalEntry.RowData rowData){
        for (CanalEntry.Column column : rowData.getAfterColumnsList()){
            System.out.println("列名:"+column.getName()+"----------变化的数据"+column.getValue());
        }
    }

    /**
     * 监听修改事件
     * @param eventType 操作事件类型(修改)
     * @param rowData 发生变化的一行数据
     */
    @UpdateListenPoint
    public void onEventUpdate(CanalEntry.EventType eventType, CanalEntry.RowData rowData){
        for (CanalEntry.Column column : rowData.getBeforeColumnsList()){
            System.out.println("修改前列名:"+column.getName()+"----------变化的数据"+column.getValue());
        }

        for (CanalEntry.Column column : rowData.getAfterColumnsList()){
            System.out.println("修改后列名:"+column.getName()+"----------变化的数据"+column.getValue());
        }
    }

    /**
     * 监听删除事件
     * @param eventType 操作事件类型(删除)
     * @param rowData 发生变化的一行数据
     */
    @DeleteListenPoint
    public void onEventDelete(CanalEntry.EventType eventType, CanalEntry.RowData rowData){
        for (CanalEntry.Column column : rowData.getBeforeColumnsList()){
            System.out.println("删除前的列名:"+column.getName()+"----------变化的数据"+column.getValue());
        }
    }

    /**
     * 自定义监听
     */
    @ListenPoint(
            eventType = {CanalEntry.EventType.INSERT, CanalEntry.EventType.DELETE, CanalEntry.EventType.UPDATE}, // 监听的事件类型
            schema = {"changgou_content"}, // 监听的库
            table = {"tb_content"} // 指定监控的表
    )
    public void onListenPoint(CanalEntry.EventType eventType, CanalEntry.RowData rowData) {
        for (CanalEntry.Column column : rowData.getBeforeColumnsList()){
            System.out.println("自定义操作前:列名:"+column.getName()+"----------变化的数据"+column.getValue());
        }
        for (CanalEntry.Column column : rowData.getAfterColumnsList()){
            System.out.println("自定义操作后:列名:"+column.getName()+"----------变化的数据"+column.getValue());
        }
    }
}
View Code

posted @ 2020-12-25 18:01  吴磊的  阅读(1274)  评论(0编辑  收藏  举报
//生成目录索引列表