【Canal】01 入门 & Kafka模式
什么是Canal (卡耐尔) ?
一、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模式
# 指定输出模式为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模式的更多相关文章
- Python学习--01入门
Python学习--01入门 Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.和PHP一样,它是后端开发语言. 如果有C语言.PHP语言.JAVA语言等其中一种语言的基础,学习Py ...
- 设计模式入门,策略模式,c++代码实现
// test01.cpp : Defines the entry point for the console application.////第一章,设计模式入门,策略模式#include &quo ...
- [译]Vulkan教程(01)入门
[译]Vulkan教程(01)入门 接下来我将翻译(https://vulkan-tutorial.com)上的Vulkan教程.这可能是我学习Vulkan的最好方式,但不是最理想的方式. 我会用“d ...
- 「从零单排canal 01」 canal 10分钟入门(基于1.1.4版本)
1.简介 canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据 订阅 和 消费.应该是阿里云DTS(Data Transfer Servi ...
- Canal详细入门实战(使用总结)
Canal介绍 Canal简介 canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费 早期阿里巴巴因为杭州和美国双机房部署,存在 ...
- RabbitMQ入门-Topic模式
上篇<RabbitMQ入门-Routing直连模式>我们介绍了可以定向发送消息,并可以根据自定义规则派发消息.看起来,这个Routing模式已经算灵活的了,但是,这还不够,我们还有更加多样 ...
- elasticsearch6.7 01.入门指南(2)
2.安装(略) 默认情况下,elasticsearch 使用端口 9200 来访问它的 REST API.如果有必要,该端口也可以配置 3.探索集群 3.1 The REST API 既然我们已经启动 ...
- 带你入门代理模式/SpringAop的运行机制
SpringAop 是spring框架中最重要的一项功能之一,同时也是企业级开发记录事物日志等不可或缺的一部分,如果说你的系统需要记录用户访问接口的操作,那SpringAop是很完美的了,当然,拦截器 ...
- canal 环境搭建 kafka Zookeeper安装(二)
第一步 创建Zookeeper 下载完成后 修改 Zookeeper中的 zoo.cfg 修改 dataDir .dataLogDir 集群模式 server.1=ServerIP:2888:3888 ...
- Spring Cloud - Nacos注册中心入门单机模式及集群模式
近几年微服务很火,Spring Cloud提供了为服务领域的一整套解决方案.其中Spring Cloud Alibaba是我们SpringCloud的一个子项目,是提供微服务开发的一站式解决方案. 包 ...
随机推荐
- js 求任意两数之间的和
知识点:函数的传参,函数的返回值 函数的传参 函数的参数包括以下两种类型: 1.形参:在定义函数时,声明的参数变量仅在函数内部可见: 2.实参:在调用函数时,实际传入的值. 示例 我们在定义函数的时候 ...
- Tomcat问题修复系列之后台缓存不足
系统运维时,在tomcat窗口发现一个警告 后台缓存收回进程无法释放上下文的缓存的10%-请考虑增加缓存的最大大小.在逐出之后,缓存中约保留XXX KB的数据. 无法将位于[/WEB-INF/view ...
- 什么是JDBC的最佳实践?
a.数据库资源是非常昂贵的,用完了应该尽快关闭它.Connection, Statement, ResultSet等JDBC对象都有close方法,调用它就好了. b.养成在代码中显式关闭掉 ...
- Future集合会等线程池执行完才开始遍历吗?
先说结论:Future集合并不是等线程池执行完才开始遍历,而是线程池内的线程执行完一条Future集合就立即遍历一条 在使用线程池的业务场景下,我们经常需要获取线程执行的返回值,此时我们需要Calla ...
- C#如何创建一个可快速重复使用的项目模板
写在前面 其实很多公司或者资深的开发都有自己快速创建项目的脚手架的,有的是魔改代码生成器实现,有的直接基于T4,RazorEngine等模板引擎打造:但无论如何,其最终目的其实就是搭建一个自定义项目模 ...
- echarts 各种特效图
饼图标签展示数值 配置项: option = { title: { text: '项目时间分布', left: 'center' }, tooltip: { trigger: 'item', form ...
- 开源一个反sql注入的asp.net core中间件
现在公安有一个专门负责信息安全的部门,前几天公司就收到了一个整改通知,防sql注入的整改. 我们公司开始对网站进行了简单的测试,普通的sql都能检测出来. 但还是被发了整改通知,肯定有些sql注入的方 ...
- 解决登录服务器报错WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
背景 登录服务器的时候报错: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @ WARNING: REMOTE HOST ID ...
- yum update和yum upgrade的区别
看见网上很多关于这个问题的解答,但是大部分都是错的,误人子弟! 很多都是执行这两个命令,然后查看系统的变化.看似严谨,实则愚蠢至极. 就算不懂内核,也应该懂得什么是内核呀!也应该懂得内核是怎么进入的啊 ...
- UBI 文件系统的支持 与 有关文件系统的image的制作
背景 UBI文件系统是一种较新类型的文件系统. 内核支持 Symbol: MTD_UBI [=y] Type : tristate Prompt: Enable UBI - Unsorted bloc ...