debezium关于cdc的使用(下)
博文原址:debezium关于cdc的使用(下)
简介
debezium在debezium关于cdc的使用(上)中有做介绍。具体可以跳到上文查看。本篇主要讲述使用kafka connector
方式来同步数据。而kafka connector实际上也有提供其他的sink(Kafka Connect JDBC)来同步数据,但是没有delete事件。所以在这里选择了Debezium MySQL CDC Connector方式来同步。本文需要使用Avro方式序列化kafka数据。
流程
第一步准备
使用kafka消息中间介的话需要对应的服务支持,尤其需要chema-registry
来管理schema,因电脑内存有限就没使用docker方式启动,如果条件ok内存够大的话阔以使用docker方式。所以使用的就是local本地方式。具体下载,安装,部署,配置环境变量我就不在重复描述了,阔以参考官方文档。
第二步启动kafka配套
进入目录后启动bin/confluent start
第三步创建kafka topic
可以通过kafka命令创建topic也可以通过Confluent Control Center
地址:http://localhost:9021
来创建topic。我们还是按照上文的表来同步数据,所以创建topic:dbserver1.inventory.demo
。
第四步创建kafka connect
可以通过kafka rest命令创建也可以使用Confluent Control Center
创建。
方便点可以使用crul创建,以下为配置文件
{
"name": "inventory-connector",
"config": {
"connector.class": "io.debezium.connector.mysql.MySqlConnector",
"tasks.max": "1",
"database.hostname": "localhost",
"database.port": "3306",
"database.user": "debezium",
"database.password": "dbz",
"database.server.id": "184054",
"database.server.name": "dbserver1",
"database.whitelist": "inventory",
"decimal.handling.mode": "double",
"key.converter": "io.confluent.connect.avro.AvroConverter",
"key.converter.schema.registry.url": "http://localhost:8081",
"value.converter": "io.confluent.connect.avro.AvroConverter",
"value.converter.schema.registry.url": "http://localhost:8081",
"database.history.kafka.bootstrap.servers": "localhost:9092",
"database.history.kafka.topic": "dbhistory.inventory"
}
}
创建好后可以使用命令查询到或者在管理中心查看。
命令:http://localhost:8083/connectors/inventory-connector
第五步启动同步程序
配置
spring:
application:
name: data-center
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/inventory_back?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
username: debe
password: 123456
jpa:
show-sql: true
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
# time-zone: UTC
kafka:
bootstrap-servers: localhost:9092
consumer:
group-id: debezium-kafka-connector
key-deserializer: "io.confluent.kafka.serializers.KafkaAvroDeserializer"
value-deserializer: "io.confluent.kafka.serializers.KafkaAvroDeserializer"
properties:
schema.registry.url: http://localhost:8081
kafka消费者
跟上文的处理流程是一样的。只不过DDL和DML分成2个监听器。
package com.example.kakfa.avro;
import com.example.kakfa.avro.sql.SqlProvider;
import com.example.kakfa.avro.sql.SqlProviderFactory;
import io.debezium.data.Envelope;
import lombok.extern.slf4j.Slf4j;
import org.apache.avro.generic.GenericData;
import org.apache.commons.lang3.StringUtils;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
import java.util.Objects;
import java.util.Optional;
@Slf4j
@Component
public class KafkaAvroConsumerRunner {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private NamedParameterJdbcTemplate namedTemplate;
@KafkaListener(id = "dbserver1-ddl-consumer", topics = "dbserver1")
public void listenerUser(ConsumerRecord<GenericData.Record, GenericData.Record> record) throws Exception {
GenericData.Record key = record.key();
GenericData.Record value = record.value();
log.info("Received record: {}", record);
log.info("Received record: key {}", key);
log.info("Received record: value {}", value);
String databaseName = Optional.ofNullable(value.get("databaseName")).map(Object::toString).orElse(null);
String ddl = Optional.ofNullable(value.get("ddl")).map(Object::toString).orElse(null);
if (StringUtils.isBlank(ddl)) {
return;
}
handleDDL(ddl, databaseName);
}
/**
* 执行数据库ddl语句
*
* @param ddl
*/
private void handleDDL(String ddl, String db) {
log.info("ddl语句 : {}", ddl);
try {
if (StringUtils.isNotBlank(db)) {
ddl = ddl.replace(db + ".", "");
ddl = ddl.replace("`" + db + "`.", "");
}
jdbcTemplate.execute(ddl);
} catch (Exception e) {
log.error("数据库操作DDL语句失败,", e);
}
}
@KafkaListener(id = "dbserver1-dml-consumer", topicPattern = "dbserver1.inventory.*")
public void listenerAvro(ConsumerRecord<GenericData.Record, GenericData.Record> record) throws Exception {
GenericData.Record key = record.key();
GenericData.Record value = record.value();
log.info("Received record: {}", record);
log.info("Received record: key {}", key);
log.info("Received record: value {}", value);
if (Objects.isNull(value)) {
return;
}
GenericData.Record source = (GenericData.Record) value.get("source");
String table = source.get("table").toString();
Envelope.Operation operation = Envelope.Operation.forCode(value.get("op").toString());
String db = source.get("db").toString();
handleDML(key, value, table, operation);
}
private void handleDML(GenericData.Record key, GenericData.Record value,
String table, Envelope.Operation operation) {
SqlProvider provider = SqlProviderFactory.getProvider(operation);
if (Objects.isNull(provider)) {
log.error("没有找到sql处理器提供者.");
return;
}
String sql = provider.getSql(key, value, table);
if (StringUtils.isBlank(sql)) {
log.error("找不到sql.");
return;
}
try {
log.info("dml语句 : {}", sql);
namedTemplate.update(sql, provider.getSqlParameterMap());
} catch (Exception e) {
log.error("数据库DML操作失败,", e);
}
}
}
数据流程
剩下的就是在inventory库中demo表中增删改数据,在对应的inventory_back库中demo表数据对应的改变。
欢迎关注微信公众号
debezium关于cdc的使用(下)的更多相关文章
- debezium关于cdc的使用(上)
博文原址:debezium关于cdc的使用(上) 简介 debezium是一个为了捕获数据变更(cdc)的开源的分布式平台.启动并指向数据库,当其他应用对此数据库执行inserts.updates.d ...
- 基于Apache Hudi和Debezium构建CDC入湖管道
从 Hudi v0.10.0 开始,我们很高兴地宣布推出适用于 Deltastreamer 的 Debezium 源,它提供从 Postgres 和 MySQL 数据库到数据湖的变更捕获数据 (CDC ...
- SQLServer数据库中开启CDC导致“事务日志空间被占满,原因为REPLICATION”的原因分析和解决办法
本文出处:http://www.cnblogs.com/wy123/p/6646143.html SQLServer中开启CDC之后,在某些情况下会导致事务日志空间被占满的现象为:在执行增删改语句(产 ...
- Kinetis Design Studio 下使用J-Link下载程序
1.安装J-Link驱动. 在KDS安装目录下已自带J-Link驱动,进入以下目录(以我的为例): C:\Freescale\KDS_1.1.1\segger\USBDriver 将看到CDC.x64 ...
- SQLServer数据库中开启CDC导致事务日志空间被占满的原因
SQLServer数据库中开启CDC导致事务日志空间被占满的原因 转载 2017-04-01 投稿:mrr 我要评论 这篇文章主要介绍了SQLServer数据库中开启CDC导致事务日志空间 ...
- 一些开源cdc框架以及工具
以下是一些cdc工具,没有包含商业软件的 zendesk maxwell 参考地址 https://github.com/zendesk/maxwell 功能 mysql 2 json 的kafaa ...
- 追踪记录每笔业务操作数据改变的利器——SQLCDC
对于大部分企业应用来用,有一个基本的功能必不可少,那就是Audit Trail或者Audit Log,中文翻译为追踪检查.审核检查或者审核记录.我们采用Audit Trail记录每一笔业务操作的基本信 ...
- 【MFC学习笔记-作业7-小型画图软件】【】
作业要求: 按下鼠标右键画圆. 按下鼠标左键移动曲线. 丝毫没有思路..网上教程又比这个程序复杂100倍... 好吧 总算找到一个合适的了... 转载至:http://blog.chinaunix.n ...
- jvm虚拟机androidy移植-编译篇
有这个必要吗?都过时的东西了,android上的Dalvik效率不够高吗,不够逼格吗? 是的但有总东西是不是我们这些码农能决定的,领导和项目需求才是你要关心的,毕竟工作要向领导汇报,项目要去挣钱钱,但 ...
随机推荐
- 没有安装zip引发的一系列安装
安装一个php框架的时候提示不能在线解压缩 通过phpinfo查看没有加载zip扩展,安装开始. 先安装了一次发现不能make,,,什么情况!!! 提示这个错误,好吧解决.make: *** No t ...
- Docker安装ElasticSearch 版本7.1.1
一.Docker 部署 ElasticSearch 1.从仓库中查找所有ElasticSearch的镜像 [root@iZwz99dhxbd6xwly17tb3bZ app]# docker sear ...
- golang mysql 如何设置最大连接数和最大空闲连接数
本文介绍golang 中连接MySQL时,如何设置最大连接数和最大空闲连接数. 关于最大连接数和最大空闲连接数,是定义在golang标准库中database/sql的. 文中例子连接MySQL用的SQ ...
- Linux命令之文件和目录操作命令(一)—— ls
本文介绍了ls命令的最常用法. 1.用法: ls [选项][目录名或文件名] 2.选项: -l 使用长格式显示目录或文件的详细信息 -a 显示隐藏文件 -h 人性化显示文件或目录的大小 -d 显示目录 ...
- Cortex-M3 双堆栈指针(MSP&PSP)
[双堆栈指针(MSP&PSP)] Cortex-M3内核中有两个堆栈指针(MSP & PSP),但任何时刻只能使用到其中一个. 复位后处于线程模式特权级,默认使用MSP. 通过SP访问 ...
- vue文件流转换成pdf预览(pdf.js+iframe)
参考文档:https://www.jianshu.com/p/242525315bf6 PDFJS: https://mozilla.github.io/pdf.js/ 支持获取文件流到客户端 ...
- C++ 学习安排
第一阶段主要是理解概念及最基本的定义和声明包含以下内容:1. 头文件2. 命名空间3. 变量和基本类型4. 函数5. 类6. 标准库类型第二部分进阶入门,主要学习C++中的某些内容的特殊性及逻辑编写1 ...
- ORA-01148:cannot refresh file size for datafile ***
ORA-01148: cannot refresh file size for datafile * Table of Contents 1. 版本信息 2. 错误信息 3. 收集错误信息 4. 故障 ...
- 在单元测试中处理Debug.Assert的好方法
在单元测试项目的配置文件中配置好, <?xml version="1.0" encoding="utf-8"?> <configuration ...
- CornerNet-Lite算法笔记
论文名称:CornerNet-Lite: Efficient Keypoint Based Object Detection 论文链接:https://arxiv.org/abs/1904.08900 ...