canal rocketmq
上篇文章canal 消费进度说到直接使用ClusterCanalConnector并发消费是有问题的,可以先用单点将canal事件发送到mq中,再由mq并发处理,另外mq还可以做到削峰的作用,让canal数据不至于阻塞。
使用队列,可以自己起一个单实例服务使用ClusterCanalConnector将消息丢队列里,也可以直接使用canal server, canal server原生支持几种队列:Kafka, RocketMQ ,RabbitMQ, PulsarMQ, 下面了解一下canal sever具体的处理过程。
canal server将消息投递到mq中
在canal server中,如果检测到配置了mq, 就会启动线程来读取bin log事件,并投递到mq中:
CanalMQStarter
while (running && destinationRunning.get()) {Message message;if (getTimeout != null && getTimeout > 0) {message = canalServer.getWithoutAck(clientIdentity,getBatchSize,getTimeout.longValue(),TimeUnit.MILLISECONDS);} else {message = canalServer.getWithoutAck(clientIdentity, getBatchSize);}final long batchId = message.getId();int size = message.isRaw() ? message.getRawEntries().size() : message.getEntries().size();if (batchId != -1 && size != 0) {canalMQProducer.send(canalDestination, message, new Callback() {@Overridepublic void commit() {canalServer.ack(clientIdentity, batchId); // 提交确认}@Overridepublic void rollback() {canalServer.rollback(clientIdentity, batchId);}}); // 发送message到topic} else {try {Thread.sleep(100);} catch (InterruptedException e) {// ignore}}}
从代码可以看到,首先调用getWithoutAck从实例获取事件,然后调用canalMQProducer.send将消息投递到队列中,如果投递成功就执行ack,否则执行rollback, 因为投递消息到队列是非常快的操作,所以这就降低了阻塞的风险。
最终发送mq消息的代码如下(CanalRocketMQProducer):
private void sendMessage(Message message, int partition) {//...SendResult sendResult = this.defaultMQProducer.send(message, (mqs, msg, arg) -> {if (partition >= mqs.size()) {return mqs.get(partition % mqs.size());} else {return mqs.get(partition);}}, null);//...}
这里有个分区的概念,对于RocketMQ来说就是队列选择,这关系到顺序消费。
业务代码使用RocketMQCanalConnector消费数据
while (running) {try {connector.connect();connector.subscribe();while (running) {List<Message> messages = connector.getListWithoutAck(1000L, TimeUnit.MILLISECONDS); // 获取messagefor (Message message : messages) {long batchId = message.getId();int size = message.getEntries().size();if (batchId == -1 || size == 0) {// try {// Thread.sleep(1000);// } catch (InterruptedException e) {// }} else {printSummary(message, batchId, size);printEntry(message.getEntries());// logger.info(message.toString());}}connector.ack(); // 提交确认}} catch (Exception e) {logger.error(e.getMessage(), e);}}connector.unsubscribe();// connector.stopRunning();
}
可以看到这和之前ClusterCanalConnector一样的处理方法,只是底层实现不一样,在subscribe的时候,调用了mq的subscribe:
public synchronized void subscribe(String filter) throws CanalClientException {//...rocketMQConsumer.subscribe(this.topic, "*");rocketMQConsumer.registerMessageListener(new MessageListenerOrderly() {@Overridepublic ConsumeOrderlyStatus consumeMessage(List<MessageExt> messageExts, ConsumeOrderlyContext context) {context.setAutoCommit(true);boolean isSuccess = process(messageExts);if (isSuccess) {return ConsumeOrderlyStatus.SUCCESS;} else {return ConsumeOrderlyStatus.SUSPEND_CURRENT_QUEUE_A_MOMENT;}}});rocketMQConsumer.start();//...}
可以看到这里使用了MessageListenerOrderly来进行顺序消费, 使用process来处理消息
private boolean process(List<MessageExt> messageExts) {//...for (MessageExt messageExt : messageExts) {//...if (!flatMessage) {Message message = CanalMessageDeserializer.deserializer(data);messageList.add(message);} else {FlatMessage flatMessage = JSON.parseObject(data, FlatMessage.class);messageList.add(flatMessage);}ConsumerBatchMessage batchMessage;if (!flatMessage) {batchMessage = new ConsumerBatchMessage<Message>(messageList);} else {batchMessage = new ConsumerBatchMessage<FlatMessage>(messageList);}try {messageBlockingQueue.put(batchMessage);} catch (InterruptedException e) {logger.error("Put message to queue error", e);throw new RuntimeException(e);}boolean isCompleted;try {isCompleted = batchMessage.waitFinish(batchProcessTimeout);} catch (InterruptedException e) {logger.error("Interrupted when waiting messages to be finished.", e);throw new RuntimeException(e);}boolean isSuccess = batchMessage.isSuccess();return isCompleted && isSuccess;}
这里将数据放到了messageBlockingQueue中,然后等待消息执行完成, ConsumerBatchMessage内置了一个CountDownLatch, batchMessage.waitFinish会阻塞在这里。
客户端使用getFlatList/getFlatListWithoutAck取数据时,就是从messageBlockingQueue取出数据,调用ack时,会释放ConsumerBatchMessage中的CountDownLatch, 这样mq消费者就可以继续从队列中拿数据了。
@Overridepublic List<Message> getListWithoutAck(Long timeout, TimeUnit unit) throws CanalClientException {if (this.lastGetBatchMessage != null) {throw new CanalClientException("mq get/ack not support concurrent & async ack");}ConsumerBatchMessage batchMessage = messageBlockingQueue.poll(timeout, unit);//...}@Overridepublic void ack() throws CanalClientException {if (this.lastGetBatchMessage != null) {this.lastGetBatchMessage.ack();}//...}
对于MessageListenerOrderly来说,是一个消费线程对应一个mq队列的,从而实现多线程消费,而这里把不同mq队列的消息在messageBlockingQueue中排队,并且使用getListWithoutAck/ack也不支持并发,又变成了单线程模式,这可能对性能造成影响,建议生产环境对性能有要求时,采用自己写代码来实现mq的消费。
配置
mq相关参数说明
相关文章:
canal rocketmq
上篇文章canal 消费进度说到直接使用ClusterCanalConnector并发消费是有问题的,可以先用单点将canal事件发送到mq中,再由mq并发处理,另外mq还可以做到削峰的作用,让canal数据不至于阻塞。 使用队列,可以自己起一个单实…...
【数据库系统概论】第九章关系查询处理何查询优化
9.1查询处理 一:查询处理步骤 关系数据库管理系统查询处理可以分为4个阶段: 查询分析查询检查查询优化查询执行 (1)查询分析 任务:对查询语句进行扫描,分析词法、语法是否符合SQL语法规则 如果没有语…...
bp盐丘模型波场数值模拟matlab
波场数值模拟是地震勘探和地震学研究中常用的工具,而BP(Backpropagation)盐丘模型是一种用于地下介质成像的方法。如果您想在MATLAB中进行波场数值模拟,并结合BP盐丘模型进行地下成像,可以按照以下步骤进行:…...
结构体对齐规则
1.第一个成员在结构体变量偏移量为0的地址处。 2.其他成员变量对齐到某个数字(对齐数)的整数倍的地址处。(对齐数编译器默认的一个对齐数与该成员大小的较小值)注意:目前有且只有VS编译器有默认为8. 3.结构体总大小为最大对齐数的整数倍。 4.如果嵌套…...
css 如何让元素内部文本和外部文本 一块显示省略号
实际上还是有这样的需求的 <div class"container"><span>啊啊啊啊啊啊啊啊</span>你好啊撒撒啊撒撒撒撒啊撒撒撒撒撒说</div>还是有这样的需求的哦。 div.container {width: 200px;white-space: nowrap;text-overflow: ellipsis;overflow:…...
SQL语句-中级
一、Mysql软件使用 1.启动/停止Mysql服务器 任务管理器 cmd命令:以管理员的身份打开cmd命令行 net start mysql80//开启net stop mysql80//停止 2.连接与断开Mysql服务器 注意要在bin目录下执行:-u用户名root,-p密码 mysql -u root -p 可能出现的…...
巧用h2-database.jar连接数据库
文章目录 一 、概述二、实践三、解决办法 一 、概述 H2 Database是一个开源的嵌入式数据库引擎,采用java语言编写,不受平台的限制,同时H2 Database提供了一个十分方便的web控制台用于操作和管理数据库内容。H2 Database还提供兼容模式&#…...
136.只出现一次的数字
136. 只出现一次的数字 - 力扣(LeetCode) 给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法来解决此问题,且…...
mysql中遇到查询字段的别名与函数冲突问题
比如以下哎,我查询城市行业数量排名 select City, DENSE_RANK() over(ORDER BY COUNT(Id) DESC) rank, COUNT(Id) num,IndustrySubGroupName from base_companyinfo WHERE IndustrySubGroupName工业机器人 GROUP BY City 上面使用 DENSE_RANK() 函数来计算排名&am…...
直播获奖
题目描述 NOI2130 即将举行。为了增加观赏性, CCF 决定逐一评出每个选手的成 绩,并直播即时的获奖分数线。本次竞赛的获奖率为 𝑤% ,即当前排名前 𝑤% 的选手的最低成绩就是即时的分数线。 更具体地,…...
选择适合自身业务的HTTP代理有哪些因素决定?
相信对很多爬虫工作者和数据采集的企业来说,如何选购适合自己业务的HTTP代理是一个特别特别困扰的选题,市面上那么多HTTP代理厂商,好像这家有这些缺点,转头又看到另外一家的缺点,要找一家心仪的仿佛大海捞针。今天我们…...
1.3 do...while实现1+...100 for实现1+...100
思路:两个变量,一个变量存储数据之和,一个变量实现自增就行 do...while int i, s;i 1;s 0;do{s 1;i;} while (i < 100);cout << s << endl; for int i, j0;for (i 1; i < 100; i){j 1;}cout << j << …...
react数据管理之setState与Props
react数据管理之setState与Props setState调用原理 setState 是 React 中用于更新组件状态(state)的方法。它的调用原理可以分为以下几个步骤: 状态的改变:当调用 setState 时,React 会将新的状态对象与当前状态对象…...
如何保护我们的网络安全
保护网络安全是至关重要的,尤其是在今天的数字化时代。以下是一些保护网络安全的基本步骤: 1、使用强密码:使用包含字母、数字和特殊字符的复杂密码。不要在多个网站上重复使用相同的密码。定期更改密码。 2、启用双因素认证 (2FA)ÿ…...
springboot 制造装备物联及生产管理ERP系统
springboot 制造装备物联及生产管理ERP系统 liu1113625581...
Google zxing 生成带logo的二维码图片
环境准备 开发环境 JDK 1.8SpringBoot2.2.1Maven 3.2 开发工具 IntelliJ IDEAsmartGitNavicat15 添加maven配置 <dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.4.0</version> </…...
使用Python计算平面多边形间最短距离
要计算平面多边形间的最短距离,首先需要导入Excel表格中的多边形数据,然后使用GJK(Gilbert-Johnson-Keerthi)算法来判断两个多边形是否重叠。如果两个多边形不重叠,可以计算它们之间的最短距离。 以下是一个基本的Pyt…...
【Python】Python语言基础(中)
第十章 Python的数据类型 基本数据类型 数字 整数 整数就是整数 浮点数 在编程中,小数都称之为浮点数 浮点数的精度问题 print(0.1 0.2) --------------- 0.30000000000000004 1.可以通过round()函数来控制小数点后位数 round(a b),则表示…...
观察者模式、订阅者发布者模式、vtk中的观察者模式
文章目录 什么是观察者模式vtk是如何实现的观察者模式.AddObserver什么时候使用观察者模式?什么使用订阅发布者模式?观察者模式的实现订阅发布者的实现总结知识补充: 什么是观察者模式 用于在对象之间建立一对多的依赖关系,当一个对象的状态发生变化时…...
关于element-ui中,页面上有多个el-table并通过v-if、v-else等控制是否显示时,type=selection勾选框失效或不显示的问题
刚开始是勾选框那一列直接空了什么都不显示,搜索了一下说是给el-table标签增加id,加了之后是显示了,但是点击任何选框都会直接取消全部选中效果,翻了半天源码也没发现到底是哪里事件冲突了还是怎么回事,烦了࿰…...
终极免费EVE舰船配置神器:Pyfa完整实战指南
终极免费EVE舰船配置神器:Pyfa完整实战指南 【免费下载链接】Pyfa Python fitting assistant, cross-platform fitting tool for EVE Online 项目地址: https://gitcode.com/gh_mirrors/py/Pyfa 在EVE Online这个充满挑战的宇宙中,打造一艘完美的…...
告别格式焦虑:用StarWind V2V Converter v9.0.1.268在ESXi 8.0和Hyper-V之间无损迁移虚拟机
跨平台虚拟机迁移实战:StarWind V2V Converter的高效应用指南 当企业IT基础设施面临升级或混合云架构转型时,虚拟机格式转换往往成为技术团队最头疼的问题之一。我曾参与过多次从VMware到Hyper-V的迁移项目,亲眼目睹了传统转换方法导致的业务…...
Docker 容器中文字体及 matplotlib 环境应用
为了避开 Noto CJK 这种复杂的 TTC(TrueType Collection)大包带来的识别问题,最理想的选择是使用独立打包的 OTF 或 TTF 字体。 0. 环境检查 # 1. 更新源并安装 fontconfig apt-get update apt-get install -y fontconfig# 2. 现在 fc-cache 命令可用了,刷新系统字体 fc-…...
Dlib零基础避坑指南:Windows Python环境一键部署实战
Dlib零基础避坑指南:Windows Python环境一键部署实战 【免费下载链接】Dlib_Windows_Python3.x Dlib compiled binary (.whl) for Python 3.7-3.11 and Windows x64 项目地址: https://gitcode.com/gh_mirrors/dl/Dlib_Windows_Python3.x 副标题:…...
PowerBuilder老系统维护指南:PB12.5连接现代数据库(如MySQL 8.0)的避坑实操
PowerBuilder老系统维护实战:PB12.5连接MySQL 8.0的七个关键步骤 当技术栈的代际差异超过十年,每一次数据库连接尝试都可能演变成一场跨越时空的调试马拉松。那些在2006年运行良好的PB12.5应用,今天面对MySQL 8.0的SSL加密要求和UTF8MB4字符集…...
5分钟搞定PaddleOCR文字识别:Python版保姆级教程(附完整代码)
5分钟极速上手PaddleOCR:Python实战指南与避坑手册 第一次接触OCR技术时,我被那些复杂的配置参数和晦涩的文档吓退了三次。直到发现PaddleOCR这个"开箱即用"的工具,才明白原来文字识别可以如此简单。本文将带你用最直接的方式&…...
零基础掌握SeleniumBasic:革新性浏览器自动化框架全攻略
零基础掌握SeleniumBasic:革新性浏览器自动化框架全攻略 【免费下载链接】SeleniumBasic A Selenium based browser automation framework for VB.Net, VBA and VBScript 项目地址: https://gitcode.com/gh_mirrors/se/SeleniumBasic 每天重复机械的网页操作…...
vLLM-v0.17.1应用场景:智能硬件语音助手离线LLM推理部署
vLLM-v0.17.1应用场景:智能硬件语音助手离线LLM推理部署 1. 技术背景与需求分析 智能硬件语音助手正在经历从云端依赖向本地化处理的转变。传统方案面临三大痛点: 网络延迟问题:云端API调用导致响应速度受限隐私安全顾虑:用户对…...
8255A工作方式0实战:手把手教你用汇编语言驱动八路抢答器LED与数码管
8255A工作方式0实战:从零构建八路抢答器驱动框架 记得第一次在实验室见到8255A芯片时,那块黑色的DIP封装器件看起来平平无奇,直到它让八颗LED随着我的汇编指令跳起"灯光芭蕾"。本文将带你深入这个经典可编程并行接口芯片的实战应用…...
Zotero Style插件:如何通过3个核心功能让文献管理效率提升200%?
Zotero Style插件:如何通过3个核心功能让文献管理效率提升200%? 【免费下载链接】zotero-style zotero-style - 一个 Zotero 插件,提供了一系列功能来增强 Zotero 的用户体验,如阅读进度可视化和标签管理,适合研究人员…...
