canal做mysql的异步传输工具
文章目录一、前言二、思路三、canal使用前mysql配置四、详细介绍Kafka模式1启动kafka模式2持久化点位重要五、简单介绍TCP模式1启动tcp模式2spring boot程序编写一、前言最近有一个项目存在着从Mysql数据库同步到oracle数据库。我有不希望在主程序上编写。因此希望用同步工具。后来发现canal可以实现以上目标canal 分为 canal‑server抓取 MySQL binlog、canal‑adapter可选同步数据库但是因为我的数据库表结构不一样因此本次项目只用到canal-server。二、思路canal-server通过抓取binlog实现文件的解析有两种模式TCP模式该模式提供11111端口用Spring boot编写canal-client实现自定义处理数据Kafka模式把数据直接推送到kafka中然后其他程序用springboot消费kafka我选择用第二种模式。这样7天的kafka数据还起到了增量备份的作用。三、canal使用前mysql配置(1) mysql必须开启日志并且日志是row类型添加以下两行。[mysqld] binlog-formatROW # 必须行模式 binlog-row-imageFULL # 必须FULLupdate要有before镜像delete要有完整行(2) 新建一个用户有replication client权限CREATEUSERcanal%IDENTIFIEDBYCanal123456;GRANTSELECT,REPLICATIONSLAVE,REPLICATIONCLIENTON*.*TOcanal%;FLUSHPRIVILEGES;四、详细介绍Kafka模式1启动kafka模式dockerrun-d\--namecanal-server-kafka\-p11111:11111\-ecanal.serverModekafka\-ekafka.bootstrap.servers192.168.1.200:9092\-ecanal.mq.topiccanal-bus-topic\-ecanal.mq.partition0\-ecanal.instance.master.address192.168.1.100:3306\-ecanal.instance.dbUsernamecanal\-ecanal.instance.dbPasswordCanal123456\-ecanal.instance.filter.regexbus_db\\.bus_info_.*\-ecanal.instance.gtidontrue\canal/canal-server:v1.1.7此时 TCP 端口 11111 虽然映射但是serverModekafkaTCP 客户端不能连接消费全部消息输出 Kafka这时候去看kafka的topic发现已经有了canal-bus-topic2持久化点位重要默认 docker 容器位点 meta.dat 存在容器内部容器删除位点丢失会重新从头消费 binlog。生产必须挂载配置目录到宿主机持久化 instance 位点文件。canal 容器内部配置目录/home/admin/canal-server/conf2.1把容器中的配置copy出来# 先启动临时容器把conf拷贝出来dockerrun--rm--nametemp-canal canal/canal-server:v1.1.7truedockercptemp-canal:/home/admin/canal-server/conf /opt/canal-docker/2.2 带挂载启动dockerrun-d\--namecanal-server-persist\-p11111:11111\-v/opt/canal-docker/conf:/home/admin/canal-server/conf\-ecanal.serverModekafka\-ekafka.bootstrap.servers192.168.1.200:9092\-ecanal.mq.topiccanal-bus-topic\canal/canal-server:v1.1.7随便到数据库里面操作一下看看kafka里是不是有数据五、简单介绍TCP模式本文的重点是kafka模式。这里稍微带过一下TCP模式1启动tcp模式dockerrun-d\--namecanal-server\-p11111:11111\-ecanal.serverModetcp\-ecanal.instance.master.address192.168.1.100:3306\-ecanal.instance.dbUsernamecanal\-ecanal.instance.dbPasswordCanal123456\-ecanal.instance.gtidontrue\# 下面这个表示只定义bus_info开头的表。实际应用的时候可以不要-ecanal.instance.filter.regexbus_db\\.bus_info_.*\canal/canal-server:v1.1.72spring boot程序编写pom.xml?xml version1.0 encodingUTF-8?projectdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring‑boot‑starter/artifactId/dependency!-- canal java客户端 --dependencygroupIdcom.alibaba.otter/groupIdartifactIdcanal‑client/artifactIdversion1.1.7/version/dependency!-- protobufcanal数据序列化依赖必须引入 --dependencygroupIdcom.google.protobuf/groupIdartifactIdprotobuf‑java/artifactIdversion3.21.9/version/dependency/dependencies/projectapplication.ymlcanal:server-host:127.0.0.1server-port:11111destination:examplebatch-size:1000# 一次批量拉取多少条核心代码配置类CanalConfig.javaimportcom.alibaba.otter.canal.client.CanalConnector;importcom.alibaba.otter.canal.client.CanalConnectors;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importjava.net.InetSocketAddress;ConfigurationpublicclassCanalConfig{Value(${canal.server-host})privateStringhost;Value(${canal.server-port})privateintport;Value(${canal.destination})privateStringdestination;Bean(destroyMethoddisconnect)publicCanalConnectorcanalConnector(){CanalConnectorconnectorCanalConnectors.newSingleConnector(newInetSocketAddress(host,port),destination,,);connector.connect();// 订阅过滤也可以在canal‑server配置这里客户端再次过滤connector.subscribe(.*\\..*);connector.rollback();returnconnector;}}监听任务 CanalMessageTask.javaimportcom.alibaba.otter.canal.client.CanalConnector;importcom.alibaba.otter.canal.protocol.CanalEntry;importcom.alibaba.otter.canal.protocol.Message;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.scheduling.annotation.EnableScheduling;importorg.springframework.scheduling.annotation.Scheduled;importorg.springframework.stereotype.Component;importjavax.annotation.PostConstruct;importjava.util.List;ComponentEnableSchedulingpublicclassCanalMessageTask{AutowiredprivateCanalConnectorcanalConnector;Value(${canal.batch-size})privateintbatchSize;PostConstructpublicvoidstartTask(){// 启动单独线程循环消费不要用Scheduled定时会丢消息newThread(this::processLoop,canal‑consumer‑thread).start();}publicvoidprocessLoop(){while(!Thread.currentThread().isInterrupted()){try{// 拉取一批消息不阻塞MessagemessagecanalConnector.getWithoutAck(batchSize);longbatchIdmessage.getId();intsizemessage.getEntries().size();if(batchId!-1size0){// 解析每一条binlog entryprocessEntry(message.getEntries());}// ✅消费完成提交ack推进位点异常不要ack下次重启重新消费这批数据canalConnector.ack(batchId);}catch(Exceptione){e.printStackTrace();// 消费异常回滚下次重新拉取canalConnector.rollback();try{Thread.sleep(1000);}catch(InterruptedExceptionex){Thread.currentThread().interrupt();}}}}/** * 解析Entry拿到行变更数据 */privatevoidprocessEntry(ListCanalEntry.EntryentryList){for(CanalEntry.Entryentry:entryList){// 只处理ROWDATA忽略事务开始、事务结束、DDLif(entry.getEntryType()!CanalEntry.EntryType.ROWDATA){continue;}CanalEntry.RowChangerowChange;try{rowChangeCanalEntry.RowChange.parseFrom(entry.getStoreValue());}catch(Exceptione){thrownewRuntimeException(parse row change error,e);}Stringdatabaseentry.getHeader().getSchemaName();StringtableNameentry.getHeader().getTableName();// DDL语句这里打印canal客户端可以拿到DDLif(rowChange.getIsDdl()){System.out.println(DDL语句:rowChange.getSql());continue;}// 遍历每一行变更for(CanalEntry.RowDatarowData:rowChange.getRowDatasList()){CanalEntry.EventTypeeventTyperowChange.getEventType();System.out.printf(【%s】库:%s 表:%s%n,eventType,database,tableName);if(eventTypeCanalEntry.EventType.INSERT){// insertafter列printColumns(rowData.getAfterColumnsList());}elseif(eventTypeCanalEntry.EventType.UPDATE){// updatebefore旧值after新值System.out.println(---before---);printColumns(rowData.getBeforeColumnsList());System.out.println(---after---);printColumns(rowData.getAfterColumnsList());}elseif(eventTypeCanalEntry.EventType.DELETE){// deletebefore旧值printColumns(rowData.getBeforeColumnsList());}// // 【这里写你的业务逻辑】// 1. 判断database、tableName过滤bus_info_xxxx分表// 2. 取出rowData里面字段做类型转换// 3. 组装实体调用Mapper写入Oracle / 其他逻辑// }}}/** * 打印列名和值 */privatevoidprintColumns(ListCanalEntry.Columncolumns){for(CanalEntry.Columncol:columns){System.out.print(col.getName()col.getValue() );}System.out.println();}}

相关新闻

Atmosphère DNS.mitm 深度解析:如何用一份 hosts 文件拦截所有域名解析并切断遥测上报

Atmosphère DNS.mitm 深度解析:如何用一份 hosts 文件拦截所有域名解析并切断遥测上报

Atmosphre DNS.mitm 深度解析:如何用一份 hosts 文件拦截所有域名解析并切断遥测上报 【免费下载链接】Atmosphere Atmosphre is a work-in-progress customized firmware for the Nintendo Switch. 项目地址: https://gitcode.com/GitHub_Trending/at/Atmosphere…

2026/10/5 13:06:59 阅读更多 →
Wand-Enhancer 完整指南:三步本地解锁 Wand 免费版 2 小时限制

Wand-Enhancer 完整指南:三步本地解锁 Wand 免费版 2 小时限制

Wand-Enhancer 完整指南:三步本地解锁 Wand 免费版 2 小时限制 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer 每天免费使用 Wand 满两…

2026/10/5 13:06:59 阅读更多 →
docker-selenium 浏览器镜像 Tag 体系全解析:以 Selenium Grid 4.29.0 + Chrome 100 为例

docker-selenium 浏览器镜像 Tag 体系全解析:以 Selenium Grid 4.29.0 + Chrome 100 为例

测试后端云原生容器编排可观测性 【免费下载链接】docker-selenium Provides a simple way to run Selenium Grid with Chrome, Firefox, and Edge using Container Platform, making it easier to perform browser automation at scale 项目地址: https://gitcode.…

2026/10/5 13:06:59 阅读更多 →

最新新闻

SpringBoot+Vue宠物健康顾问系统:从架构设计到前后端分离实践

SpringBoot+Vue宠物健康顾问系统:从架构设计到前后端分离实践

1. 项目概览:这个“宠物健康顾问”到底是什么 先说结论:这套SpringBootVue的宠物健康顾问系统,核心是做“宠物医院的轻量级数字化管理”。它不是一个花架子demo,而是把真实宠物门诊日常要干的几件事——宠物档案建档、在线问诊、疫…

2026/10/5 13:57:20 阅读更多 →
SpringBoot+Vue宠物健康顾问系统全栈开发实战解析

SpringBoot+Vue宠物健康顾问系统全栈开发实战解析

毕业后第一次做全栈项目,不少人会直接选“宠物健康顾问系统”。说实话,这个题目在毕设和课设里出现的频率相当高,数据模型清晰、业务边界明确、技术栈又刚好踩在主流Java后端和前端框架上,用来锻炼完整的项目开发流程再合适不过。…

2026/10/5 13:57:20 阅读更多 →
Ubuntu 20.04 源码编译 OpenCV 3.3.1 全流程与避坑指南

Ubuntu 20.04 源码编译 OpenCV 3.3.1 全流程与避坑指南

简介:针对 Ubuntu 20.04 重新适配的 OpenCV 3.3.1 资源包,面向需要在较新系统上编译旧版 OpenCV 的开发者、人工智能与计算机视觉学习者。作者已修正 CODEC_FLAG_GLOBAL_HEADER、AVFMT_RAWPICTURE 未声明及 const char* 转 char* 等编译错误,…

2026/10/5 13:56:20 阅读更多 →
苏凌丘国庆希尔顿酒店举办订婚宴 学霸女神情定金秋

苏凌丘国庆希尔顿酒店举办订婚宴 学霸女神情定金秋

(2026年10月3日) 国庆佳节,喜事临门。曾因江苏卫视《非诚勿扰》备受关注的“学霸女神”苏凌丘,于国庆在希尔顿酒店举办订婚宴,正式与男友许下携手一生的承诺。这是继今年8月男友在W酒店秘密求婚后,两人感情…

2026/10/5 13:56:20 阅读更多 →
用 @Docs 与项目 README 约束幻觉:Cursor 文档索引配置与提问模板

用 @Docs 与项目 README 约束幻觉:Cursor 文档索引配置与提问模板

用 Docs 与项目 README 约束幻觉:Cursor 文档索引配置与提问模板 Agent 「一本正经地胡说」时,观众爱骂模型;工程上更常缺的是材料与约束:没有版本对齐的文档索引,没有当真相源的 README,提问又允许它「凭印…

2026/10/5 13:56:20 阅读更多 →
Python自动化:PPT一键转视频的完整技术方案与代码实践

Python自动化:PPT一键转视频的完整技术方案与代码实践

做这行的朋友应该都有过这种经历:汇报前夜改了八遍PPT,第二天发现讲稿和页面顺序对不上;或者要录一节网课,手动点鼠标翻页加录音折腾到凌晨。当"幻灯片"和"视频"这两个词出现在同一个需求里,很多人…

2026/10/5 13:56:20 阅读更多 →

日新闻

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

马斯克杀回智能体战场,Grok 4.5万亿参数撑腰,Cursor接手数字白领项目:用TaoToken统一Key跑通多模型Agent工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:22 阅读更多 →
AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

AI编程工具插件机制详解:plugin.json配置与加载失败排查指南

1. 从“plugins”这个词说起:它到底在解决什么问题如果你最近在折腾 AI 编程工具,尤其是 Cursor、Codex CLI、Claude Code 这类带 CLI 的编辑器或命令行助手,那你大概率绕不开一个词——plugins。这个词本身不新鲜,从浏览器到 IDE…

2026/10/5 0:00:23 阅读更多 →
第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

第26课:OpenClaw|日志审计与问题诊断:把日志链路改到 TaoToken 的排查清单

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 0:00:23 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 5:06:42 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 1:10:22 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/5 3:06:17 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 11:40:45 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 9:43:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/4 20:14:29 阅读更多 →