canal同步mysql到kafka,canal同步数据到kafka配置及源码

canal.properties 配置

86e4ba9776f91bb35092ed7ae35d9c58.png

b2732ef5ad3fde668a7cc66d02592015.png

instance.properties 配置

de91f1ad34a37615840bbb16144871cb.png

kafka的 server.properties 配置

0c03afd2a82858b60d357293a933fba1.png

canal客户端代码

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.example.demo.kafka.KafkaClient;

import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;

import java.util.List;

@Component

public class CannalClient {

private final static int BATCH_SIZE = 1000;

public void canalService() {

// 创建连接

CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress("localhost", 11111), "example", "", "");

try {

// 打开连接

connector.connect();

// 订阅数据库表,全部表

connector.subscribe(".*\\..*");

// 回滚到未进行 ack 的地方,下次 fetch 的时候,可以从最后一个没有 ack 的地方开始拿

connector.rollback();

while (true) {

// 获取指定数量的数据

Message message = connector.getWithoutAck(BATCH_SIZE);

// 获取批量 ID

long batchId = message.getId();

// 获取批量的数量

int size = message.getEntries().size();

// 如果没有数据

if (batchId == -1 || size == 0) {

try {

// 线程休眠 2 秒

Thread.sleep(2000);

} catch (InterruptedException e) {

e.printStackTrace();

}

} else {

List entries = message.getEntries();

for (CanalEntry.Entry entry : entries) {

if (entry.getEntryType().equals(CanalEntry.EntryType.ROWDATA)){

if (entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONBEGIN || entry.getEntryType() == CanalEntry.EntryType.TRANSACTIONEND){

continue;

}

// 获取 storevalue,并反序列化

CanalEntry.RowChange rowChage;

try{

rowChage = CanalEntry.RowChange.parseFrom(entry.getStoreValue());

}catch (Exception e){

throw new RuntimeException("ERROR ## parser of eromanga-event has an error , data:" + entry.toString(), e);

}

// 获取当前entry是对哪个表的操作结果

String tableName = entry.getHeader().getTableName();

handle(tableName, rowChage);

}

}

}

connector.ack(batchId);

}

} catch (Exception e) {

e.printStackTrace();

} finally {

connector.disconnect();

}

}

private static void handle(String tableName, CanalEntry.RowChange rowChange){

String canaltopic = "canaltopic";

String partition = "partition10";

//获取操作类型:insert/update/delete类型

CanalEntry.EventType eventType = rowChange.getEventType();

if (eventType.equals(CanalEntry.EventType.INSERT)){

List rowDataList = rowChange.getRowDatasList();

for (CanalEntry.RowData rowData : rowDataList){

JSONObject jsonObject = new JSONObject();

List afterColumnList = rowData.getAfterColumnsList();

for (CanalEntry.Column column : afterColumnList){

jsonObject.put(column.getName(), column.getValue());

}

// 将数据发送到 kafka

KafkaClient.send(canaltopic, partition, jsonObject.toString());

}

}

}

}

kafka 生产者代码

import org.apache.kafka.clients.producer.KafkaProducer;

import org.apache.kafka.clients.producer.Producer;

import org.apache.kafka.clients.producer.ProducerRecord;

import org.springframework.stereotype.Component;

import java.util.*;

@Component

public class KafkaClient {

private static Producer producer;

static {

producer = createProducer();

}

//创建Producer

public static Producer createProducer(){

//kafka连接的配置信息

Properties properties = new Properties();

properties.put("bootstrap.servers","localhost:9092");

properties.put("key.serializer","org.apache.kafka.common.serialization.StringSerializer");

properties.put("value.serializer","org.apache.kafka.common.serialization.StringSerializer");

KafkaProducer kafkaProducer = new KafkaProducer<>(properties);

return kafkaProducer;

}

//将数据写入到kafka

public static void send(String topic, String partition, String value){

producer.send(new ProducerRecord<>(topic, partition, value));

}

}

kafka 消费者代码

import java.time.Duration;

import java.util.*;

import java.util.function.Function;

import java.util.stream.Collectors;

import org.apache.kafka.clients.consumer.*;

import org.apache.kafka.common.PartitionInfo;

import org.apache.kafka.common.TopicPartition;

import org.springframework.stereotype.Component;

@Component

public class KafkaConsumerOps{

private static Consumer consumer;

static {

consumer = createConsumer();

}

//创建Producer

public static Consumer createConsumer() {

//kafka连接的配置信息

Properties properties = new Properties();

properties.put("bootstrap.servers","localhost:9092");

properties.put("group.id", "logGroup");

properties.put("enable.auto.commit", "false");

properties.put("session.timeout.ms", "30000");

properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");

properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");

Consumer consu = new KafkaConsumer(properties);

return consu;

}

// 数据从kafka中进行消费

public static void consumerOps(){

//消费者订阅topic

consumer.subscribe(Collections.singletonList("canaltopic")); // 指定 topic 进行消费

try {

while (true) {

ConsumerRecords records = consumer.poll(Duration.ofMillis(300));

for (ConsumerRecord record : records) {

System.out.println("topic ==>> " + record.topic() + ", partition ==>> " + record.partition()

+ ", offset ==>>" + record.offset() + ", key ==>>" + record.key() + ", value ==>>" + record.value());

try{

consumer.commitAsync();

}catch (Exception e){

e.printStackTrace();

}finally {

try {

consumer.commitSync();

}catch (Exception e){

e.printStackTrace();

}

}

}

}

} finally {

consumer.close();

}

}

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用Canal来实现将MySQL数据同步Kafka。Canal是阿里巴巴开源的一款基于MySQL数据库增量日志解析和同步的工具,可以实时捕获MySQL数据库的增量日志,解析日志内容,并将解析后的数据发送到Kafka等消息队列中。 具体实现步骤如下: 1. 安装Canal配置MySQL数据源信息。 2. 配置CanalKafka输出端,包括Kafka的地址、topic等信息。 3. 启动Canal服务,并开启Kafka输出端。 4. 在MySQL数据库中进行数据操作,Canal会实时捕获增量日志并将解析后的数据发送到Kafka中。 通过以上步骤,就可以实现将MySQL数据同步Kafka中。 ### 回答2: Canal是一个开源的MySQL数据数据同步工具,可用于将MySQL数据库中的数据推送到Kafka等消息队列系统中。Canal具有简单易用和高效稳定等特点,可以实时地将MySQL的操作事件转换为消息发布到Kafka中,从而实现数据的传输和同步。 Canal数据同步过程主要分为三个步骤:数据的抽取、数据的传输和数据的写入。在数据的抽取阶段,Canal会通过监听MySQL的binlog日志来实时获取数据库的更新操作事件。在数据的传输阶段,Canal会将获取到的数据转化为Kafka数据结构并将数据推送到Kafka中。在数据的写入阶段,Kafka消费者会接收到Canal推送过来的数据并将数据写入到目标数据库中。 Canal同步MySQL数据Kafka具有以下优点: 1. 实时性好:Canal可以实时获取MySQL的binlog日志,因此同步数据的速度较快,数据可以实时同步Kafka中,提高了数据同步的实时性。 2. 高效稳定:Canal具有高效稳定的数据同步能力,可以对MySQL的大量数据进行实时同步,同时Canal对复杂的数据类型和操作也具有很好的兼容性。 3. 低延迟:Canal同步MySQL数据Kafka的过程中,除了Canal本身的处理时间外,数据传输和写入等步骤都可以实现实时同步,因此具有低延迟的特点。 4. 扩展性强:Canal支持插件机制,可以根据需要进行扩展和定制,支持多种不同的数据源和目标,也支持多线程和分布式部署等高级特性。 总之,Canal同步MySQL数据Kafka是一种高效稳定、实时性好、低延迟、扩展性强的数据同步方案。在实际的数据同步应用中,可以根据具体情况选择适合自己的部署方式和应用场景,并结合其他工具和技术进行更加灵活高效的数据同步。 ### 回答3: Canal是阿里巴巴公司开发的一款基于binlog的增量数据同步工具,可以把MySQL数据库的数据变更同步Kafka等消息队列或其他存储介质中。 Canal架构包括三个组件:Canal Server、Canal Client和Canal Adapter。 Canal Server是作为数据源的MySQL数据库的代理工具,负责解析MySQL的binlog日志,并将变更事件以JSON的形式发送给Canal Client。 Canal Client是Canal数据同步的传输逻辑,接受Canal Server解析出来的binlog事件,并将事件转化为适合Kafka等消息队列的消息格式。 Canal Adapter是Canal的一个插件式架构,根据业务需求,可以通过Adapter来将数据发送到Kafka或其他消息队列、ElasticSearch等存储介质中。 在使用Canal同步MySQL数据Kafka时,需要配置Canal Server和Canal Client,其中Canal Server需要连接MySQL数据库,并开启Binlog日志功能。Canal Client需要连接Canal Server,接收MySQL数据库的变更事件,并将事件转换为对应的消息格式发送到Kafka中。 同时,需要根据业务需求配置Canal Adapter,将MySQL数据库的数据变更事件转化为Kafka消息队列的消息格式,并发送到Kafka中。 总之,Canal是一款可靠高效的增量数据同步工具,可以帮助企业快速实现数据的分布式同步和多数据源之间的数据交换。在实际应用中,可以结合其他开源工具,如Flink、Presto等,构建出一套全方位的数据处理和分析平台,实现数据的快速处理和洞察。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值