什么是Canal (卡耐尔) ?

Canal 是用 Java 开发的基于数据库增量日志解析,提供增量数据订阅&消费的中间件
原理基于MySQL的binlog从库监听
 
 
 

一、MySQL环境配置

1、更改MySQL配置 (my.ini / my.cnf):

[mysqld]

# 主库id标识
server-id=1 # 开启binlog日志
log-bin=mysql-bin # 日志格式类型
binlog_format=row # (可选)声明只对哪个库进行日志输出
binlog-do-db=gmall-2021

2、测试用例

没有表就创建一个测试用的表:

CREATE TABLE user_info(
  `id` VARCHAR(255),
  `name` VARCHAR(255),
  `sex` VARCHAR(255)
);

3、监听的账号

和主从复制一样,需要提供一个从库监听的账号:

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

二、安装Canal

Linux平台:

# 解压方式一
tar -zxvf canal.deployer-1.1.2.tar.gz mkdir canal.deployer-1.1.2 mv bin canal.deployer-1.1.2/
mv logs canal.deployer-1.1.2/
mv lib canal.deployer-1.1.2/
mv conf canal.deployer-1.1.2/ # 解压方式二
mkdir ~/canal-1.1.2
tar -zxvf canal.deployer-1.1.2.tar.gz -C ~/canal-1.1.2/

Windows平台:

新建一个canal的目录,然后打开目录
把压缩包内容解压到目录中即可

通用配置操作:

案例只是为了演示,单机运行的方式进行配置

# 备份 instance.properties文件
cd ~/canal-1.1.2/example
cp instance.properties instance.properties.bak

编辑example下的实例文件

vim ~/canal-1.1.2/conf/example/instance.properties

关键参数项:

# 伪装从库的id,不要和主库id一致即可
canal.instance.mysql.slaveId=20
# 主库IP地址和端口号
canal.instance.master.address=192.168.2.225:3308
# 主库开设的监听账号
canal.instance.dbUsername=canal
canal.instance.dbPassword=123456
# 字符集
canal.instance.connectionCharset=UTF-8
# 默认监听的db?
canal.instance.defaultDatabaseName=canal

三、启动,关闭Canal

restart.sh
startup.bat
startup.sh
stop.sh # windows 平台直接运行 startup.bat
# 关闭就是直接关闭终端窗口即可
startup.bat # linux 平台
startup.
sh # 启动
restart.sh # 重启
stop.sh # 停止

四、创建Canal监听客户端:

canal没有提供默认的终端输出,强制要求客户端监听日志消息:

这里使用Java做一个客户端来查看消息

创建普通Maven项目,引入两个依赖

<dependencies>
<dependency>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal.client</artifactId>
<version>1.1.2</version>
</dependency> <dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.4.1</version>
</dependency>
</dependencies>

客户端类:

import com.alibaba.fastjson.JSONObject;
import com.alibaba.otter.canal.client.CanalConnector;
import com.alibaba.otter.canal.client.CanalConnectors;
import com.alibaba.otter.canal.protocol.CanalEntry;
import com.alibaba.otter.canal.protocol.Message;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException; import java.net.InetSocketAddress;
import java.util.List; public class CanalClient { public static void main(String[] args) throws InterruptedException, InvalidProtocolBufferException { //TODO 获取连接
CanalConnector canalConnector = CanalConnectors.newSingleConnector(new InetSocketAddress("127.0.0.1", 11111), "example", "", ""); while (true) { //TODO 连接
canalConnector.connect(); //TODO 订阅数据库
canalConnector.subscribe("canal.*"); //TODO 获取数据
Message message = canalConnector.get(100); //TODO 获取Entry集合
List<CanalEntry.Entry> entries = message.getEntries(); //TODO 判断集合是否为空,如果为空,则等待一会继续拉取数据
if (entries.size() <= 0) {
System.out.println("当次抓取没有数据,休息一会。。。。。。");
Thread.sleep(1000);
} else { //TODO 遍历entries,单条解析
for (CanalEntry.Entry entry : entries) { //1.获取表名
String tableName = entry.getHeader().getTableName(); //2.获取类型
CanalEntry.EntryType entryType = entry.getEntryType(); //3.获取序列化后的数据
ByteString storeValue = entry.getStoreValue(); //4.判断当前entryType类型是否为ROWDATA
if (CanalEntry.EntryType.ROWDATA.equals(entryType)) { //5.反序列化数据
CanalEntry.RowChange rowChange = CanalEntry.RowChange.parseFrom(storeValue); //6.获取当前事件的操作类型
CanalEntry.EventType eventType = rowChange.getEventType(); //7.获取数据集
List<CanalEntry.RowData> rowDataList = rowChange.getRowDatasList(); //8.遍历rowDataList,并打印数据集
for (CanalEntry.RowData rowData : rowDataList) { JSONObject beforeData = new JSONObject();
List<CanalEntry.Column> beforeColumnsList = rowData.getBeforeColumnsList();
for (CanalEntry.Column column : beforeColumnsList) {
beforeData.put(column.getName(), column.getValue());
} JSONObject afterData = new JSONObject();
List<CanalEntry.Column> afterColumnsList = rowData.getAfterColumnsList();
for (CanalEntry.Column column : afterColumnsList) {
afterData.put(column.getName(), column.getValue());
} //数据打印
System.out.println("Table:" + tableName +
",EventType:" + eventType +
",Before:" + beforeData +
",After:" + afterData);
}
} else {
System.out.println("当前操作类型为:" + entryType);
}
}
}
}
}
}

开启后,想指定的表中写入数据:

客户端输出消息:

当次抓取没有数据,休息一会。。。。。。
当次抓取没有数据,休息一会。。。。。。
当次抓取没有数据,休息一会。。。。。。
当次抓取没有数据,休息一会。。。。。。
当前操作类型为:TRANSACTIONBEGIN
Table:user_info,EventType:INSERT,Before:{},After:{
"sex":"男","name":"张三","id":"1"}
当前操作类型为:TRANSACTIONEND
当前操作类型为:TRANSACTIONBEGIN
Table:user_info,EventType:INSERT,Before:{},After:{"sex":"男","name":"张三","id":"2"
}
当前操作类型为:TRANSACTIONEND

当次抓取没有数据,休息一会。。。。。。

五、Kafka模式

修改 canal.properties
# 指定输出模式为kafka
canal.serverMode = kafka # kafka集群地址,如单机,则写一个即可
canal.mq.servers = hadoop102:9092,hadoop103:9092,hadoop104:9092

修改 example/instance.properties

# mq config
# 指定Topic名称 和 分区数量
canal.mq.topic=canal_test
canal.mq.partitionsNum=1

重启canal以加载配置信息

启动Kafka消费者来查看是否运行:

bin/kafka-console-consumer.sh --bootstrap-server hadoop102:9092 --topic canal_test

执行插入SQL:

INSERT INTO user_info VALUES('1001','zhangsan','male'),('1002','lisi','female');

Kafka控制台:

{
"data": [
{
"id": "1001",
"name": "zhangsan",
"sex": "male"
},
{
"id": "1002",
"name": "lisi",
"sex": "female"
}
],
"database": "gmall-2021",
"es": 1639360729000,
"id": 1,
"isDdl": false,
"mysqlType": {
"id": "varchar(255)",
"name": "varchar(255)",
"sex": "varchar(255)"
},
"old": "null",
"sql": "",
"sqlType": {
"id": 12,
"name": 12,
"sex": 12
},
"table": "user_info",
"ts": 1639361038454,
"type": "INSERT"
}
 
 

【Canal】01 入门 & Kafka模式的更多相关文章

  1. Python学习--01入门

    Python学习--01入门 Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.和PHP一样,它是后端开发语言. 如果有C语言.PHP语言.JAVA语言等其中一种语言的基础,学习Py ...

  2. 设计模式入门,策略模式,c++代码实现

    // test01.cpp : Defines the entry point for the console application.////第一章,设计模式入门,策略模式#include &quo ...

  3. [译]Vulkan教程(01)入门

    [译]Vulkan教程(01)入门 接下来我将翻译(https://vulkan-tutorial.com)上的Vulkan教程.这可能是我学习Vulkan的最好方式,但不是最理想的方式. 我会用“d ...

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

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

  5. Canal详细入门实战(使用总结)

    Canal介绍 Canal简介 canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费 早期阿里巴巴因为杭州和美国双机房部署,存在 ...

  6. RabbitMQ入门-Topic模式

    上篇<RabbitMQ入门-Routing直连模式>我们介绍了可以定向发送消息,并可以根据自定义规则派发消息.看起来,这个Routing模式已经算灵活的了,但是,这还不够,我们还有更加多样 ...

  7. elasticsearch6.7 01.入门指南(2)

    2.安装(略) 默认情况下,elasticsearch 使用端口 9200 来访问它的 REST API.如果有必要,该端口也可以配置 3.探索集群 3.1 The REST API 既然我们已经启动 ...

  8. 带你入门代理模式/SpringAop的运行机制

    SpringAop 是spring框架中最重要的一项功能之一,同时也是企业级开发记录事物日志等不可或缺的一部分,如果说你的系统需要记录用户访问接口的操作,那SpringAop是很完美的了,当然,拦截器 ...

  9. canal 环境搭建 kafka Zookeeper安装(二)

    第一步 创建Zookeeper 下载完成后 修改 Zookeeper中的 zoo.cfg 修改 dataDir .dataLogDir 集群模式 server.1=ServerIP:2888:3888 ...

  10. Spring Cloud - Nacos注册中心入门单机模式及集群模式

    近几年微服务很火,Spring Cloud提供了为服务领域的一整套解决方案.其中Spring Cloud Alibaba是我们SpringCloud的一个子项目,是提供微服务开发的一站式解决方案. 包 ...

随机推荐

  1. js 求任意两数之间的和

    知识点:函数的传参,函数的返回值 函数的传参 函数的参数包括以下两种类型: 1.形参:在定义函数时,声明的参数变量仅在函数内部可见: 2.实参:在调用函数时,实际传入的值. 示例 我们在定义函数的时候 ...

  2. Tomcat问题修复系列之后台缓存不足

    系统运维时,在tomcat窗口发现一个警告 后台缓存收回进程无法释放上下文的缓存的10%-请考虑增加缓存的最大大小.在逐出之后,缓存中约保留XXX KB的数据. 无法将位于[/WEB-INF/view ...

  3. 什么是JDBC的最佳实践?

    a.数据库资源是非常昂贵的,用完了应该尽快关闭它.Connection,   Statement,    ResultSet等JDBC对象都有close方法,调用它就好了. b.养成在代码中显式关闭掉 ...

  4. Future集合会等线程池执行完才开始遍历吗?

    先说结论:Future集合并不是等线程池执行完才开始遍历,而是线程池内的线程执行完一条Future集合就立即遍历一条 在使用线程池的业务场景下,我们经常需要获取线程执行的返回值,此时我们需要Calla ...

  5. C#如何创建一个可快速重复使用的项目模板

    写在前面 其实很多公司或者资深的开发都有自己快速创建项目的脚手架的,有的是魔改代码生成器实现,有的直接基于T4,RazorEngine等模板引擎打造:但无论如何,其最终目的其实就是搭建一个自定义项目模 ...

  6. echarts 各种特效图

    饼图标签展示数值 配置项: option = { title: { text: '项目时间分布', left: 'center' }, tooltip: { trigger: 'item', form ...

  7. 开源一个反sql注入的asp.net core中间件

    现在公安有一个专门负责信息安全的部门,前几天公司就收到了一个整改通知,防sql注入的整改. 我们公司开始对网站进行了简单的测试,普通的sql都能检测出来. 但还是被发了整改通知,肯定有些sql注入的方 ...

  8. 解决登录服务器报错WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

    背景 登录服务器的时候报错: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST ID ...

  9. yum update和yum upgrade的区别

    看见网上很多关于这个问题的解答,但是大部分都是错的,误人子弟! 很多都是执行这两个命令,然后查看系统的变化.看似严谨,实则愚蠢至极. 就算不懂内核,也应该懂得什么是内核呀!也应该懂得内核是怎么进入的啊 ...

  10. UBI 文件系统的支持 与 有关文件系统的image的制作

    背景 UBI文件系统是一种较新类型的文件系统. 内核支持 Symbol: MTD_UBI [=y] Type : tristate Prompt: Enable UBI - Unsorted bloc ...