Maxwell 底层原理 详解
Maxwell 是一个 MySQL 数据库的增量数据捕获(CDC, Change Data Capture)工具,它通过读取 MySQL 的 binlog(Binary Log)来捕获数据变化,并将这些变化实时地发送到如 Kafka、Kinesis、RabbitMQ 或其他输出端。Maxwell 允许用户捕捉到 INSERT、UPDATE、DELETE 等操作的记录,并将其以 JSON 格式发送到下游系统,用于数据同步、分析、实时监控等应用场景。
要详细解释 Maxwell 的底层原理及源代码,我们需要从 MySQL binlog 的工作机制、Maxwell 如何解析 binlog、内部架构的各个核心组件、事件处理机制等多方面进行深入解析。
1. MySQL binlog 工作原理
MySQL 的 binlog 是记录数据库事务性和非事务性数据变化的二进制日志文件,所有的 INSERT、UPDATE、DELETE 以及对表结构的更改操作(如 ALTER TABLE)都会写入 binlog 中。这使得 binlog 成为数据库增量数据捕获的重要来源。
binlog 具有两种格式:
- ROW 格式:记录每一行的数据变化,捕捉到行级别的增删改操作。
- STATEMENT 格式:记录 SQL 语句本身的执行。
- MIXED 格式:结合了 ROW 和 STATEMENT 两种格式。
➢ 三种格式的区别:
◼ statement
语句级,binlog 会记录每次一执行写操作的语句。相对 row 模式节省空间,但是可能产生不一致性,比如update test set create_date=now();如果用 binlog 日志进行恢复,由于执行时间不同可能产生的数据就不同。优点: 节省空间 缺点: 有可能造成数据不一致。
◼ row
行级, binlog 会记录每次操作后每行记录的变化。优点:保持数据的绝对一致性。因为不管 sql 是什么,引用了什么函数,他只记录执行后的效果。缺点:占用较大空间。
◼ mixed
混合级别,statement 的升级版,一定程度上解决了 statement 模式因为一些情况而造成的数据不一致问题。默认还是 statement,在某些情况下,譬如:当函数中包含 UUID() 时;包含 AUTO_INCREMENT 字段的表被更新时;执行 INSERT DELAYED 语句时;用 UDF 时;会按照 ROW 的方式进行处理 优点:节省空间,同时兼顾了一定的一致性。缺点:还有些极个别情况依旧会造成不一致,另外 statement 和 mixed 对于需要对binlog 监控的情况都不方便。
Maxwell 依赖的是 ROW 格式,因为 ROW 格式可以直接获取到数据变化的细节,如具体哪一行数据发生了修改,这对于实时的数据同步和分析非常关键。
2. Maxwell 架构与工作流程
Maxwell 的架构可以概括为以下几个部分:
- Binlog Position 监控:Maxwell 会从 MySQL 的 binlog 文件中读取增量变化事件,且会记录当前读取到的 binlog 文件的位置(position),以保证在 Maxwell 重启后能够继续从上次的位置读取。
- Binlog 解析:Maxwell 通过解析 MySQL 的 binlog 文件来获取数据的变化详情(包括表名、列值、操作类型等)。
- 事件处理器(Event Processor):解析后的 binlog 数据会通过 Maxwell 的事件处理器进行处理,并转换为 JSON 格式。
- 输出适配器(Producer Adapter):Maxwell 支持将处理后的数据发送到多个目标输出(如 Kafka、Kinesis 等)。
2.1 核心组件
Maxwell 的底层工作机制由以下几个核心组件协同实现:
-
BinlogConnectorReplicator
- 负责与 MySQL 进行通信并获取 binlog 数据。
- 使用 MySQL Binary Log Client Library 实现 binlog 的读取和消费。Maxwell 通过
BinlogConnectorReplicator
连接 MySQL,获取实时的 binlog 数据。
-
BinlogParser
- 负责将二进制格式的 binlog 转换为可理解的事件对象。
- 它解析 ROW 格式的 binlog 并将其转换为 Maxwell 可以处理的内部事件对象(如 Insert、Update、Delete 事件)。
-
MaxwellContext
- 管理 Maxwell 的运行状态,包括当前的 binlog position、错误处理、断点续传等。
MaxwellContext
还负责维护 Maxwell 的元数据(如表结构缓存、上次处理的 binlog 位置等),以保证数据的一致性和容错性。
-
MaxwellReplicator
MaxwellReplicator
是系统的核心执行器,它从BinlogConnectorReplicator
获取 binlog 数据,并通过BinlogParser
解析这些数据,生成RowMap
对象(用于描述数据变化)。 -
RowMap
RowMap
是 Maxwell 对数据变更的内部抽象,它将 binlog 中的行变化转化为键值对的形式,包含了表名、数据库名、操作类型(insert、update、delete)以及具体的行数据。 -
Producer
Producer
是事件发布器,它负责将处理过的事件推送到外部系统(如 Kafka、Kinesis、文件等)。- Producer 将
RowMap
转换为 JSON 格式并将其发送至指定的输出端。
2.2 事件流处理流程
Maxwell 的数据流处理可以分为以下几个步骤:
- 读取 binlog:Maxwell 通过
BinlogConnectorReplicator
从 MySQL binlog 中读取最新的事件。 - 解析 binlog:
BinlogParser
将 binlog 的二进制数据解析为内部事件对象(如Insert
、Update
、Delete
事件)。 - 生成事件对象:解析后的 binlog 事件会被封装为
RowMap
对象,RowMap
中包含了数据库名、表名、操作类型、变更的数据行内容。 - 事件发布:通过
Producer
,Maxwell 将RowMap
转换为 JSON 格式,并发送到外部系统,如 Kafka、Kinesis 等。
格式数据举例
json 字段的说明:字段
解释
database
变更数据所属的数据库
table
表更数据所属的表
type
数据变更类型
ts
数据变更发生的时间
xid
事务id
commit
事务提交标志,可用于重新组装事务
data
对于insert类型,表示插入的数据;对于update类型,标识修改之后的数据;对于delete类型,表示删除的数据
old
对于update类型,表示修改之前的数据,只包含变更字段
3. 源代码分析
为了更详细地解释 Maxwell 的工作原理,接下来分析其核心类的部分源代码。
3.1 BinlogConnectorReplicator
(binlog 读取器)
BinlogConnectorReplicator
是 Maxwell 通过 binlog client 读取 MySQL binlog 数据的核心组件。它负责通过 MySQL Replication 协议从 MySQL 实例拉取 binlog 事件。
public class BinlogConnectorReplicator extends AbstractReplicator {private BinaryLogClient client;private MaxwellFilter filter;public BinlogConnectorReplicator(MaxwellContext context, Position startPosition) throws Exception {super(context);this.client = new BinaryLogClient(context.getConfig().mysqlHost,context.getConfig().mysqlPort,context.getConfig().mysqlUser,context.getConfig().mysqlPassword);// 设置监听器处理 binlog 事件client.registerEventListener(this::handleEvent);}public void start() throws IOException {// 启动客户端开始从 binlog 中获取数据client.connect();}private void handleEvent(Event event) {// 处理 binlog 事件// 将 event 转换为 Maxwell 的 RowMap 对象}
}
在上面的代码中:
BinaryLogClient
是用来与 MySQL binlog 进行通信的核心类,它会与 MySQL 建立连接并监听 binlog 的变化。handleEvent
方法会被 MySQL binlog 的事件触发,当 binlog 中有新事件时,该方法会被调用,将事件处理并转换为 Maxwell 的内部对象。
3.2 BinlogParser
(binlog 解析器)
BinlogParser
负责将从 binlog 中获取的二进制事件解析为 Maxwell 可以理解的对象。对于每个 binlog 事件,都会转换为相应的 RowMap
对象。
public class BinlogParser {public RowMap parse(Event event) {EventType type = event.getHeader().getEventType();// 根据 binlog 事件类型处理不同的操作switch (type) {case WRITE_ROWS:return handleInsertEvent(event);case UPDATE_ROWS:return handleUpdateEvent(event);case DELETE_ROWS:return handleDeleteEvent(event);default:return null;}}private RowMap handleInsertEvent(Event event) {// 解析 insert 事件,将其封装为 RowMap}private RowMap handleUpdateEvent(Event event) {// 解析 update 事件,将其封装为 RowMap}private RowMap handleDeleteEvent(Event event) {// 解析 delete 事件,将其封装为 RowMap}
}
在 BinlogParser
中:
parse
方法会根据事件类型(如WRITE_ROWS
、UPDATE_ROWS
、DELETE_ROWS
)调用对应的处理方法,将事件转换为RowMap
。RowMap
是用于描述数据变化的核心对象,包含了具体的数据变化信息。
3.3 RowMap
(事件描述对象)
RowMap
是 Maxwell 中的核心数据结构,负责存储解析后的 binlog 数据。它包含了数据库名、表名、操作类型(如 insert、update、delete)以及具体的列值数据。
public class RowMap {private String database;private String table;private String type; // insert, update, deleteprivate Map<String, Object> data;public RowMap(String database, String table, String type) {this.database = database;this.table = table;this.type = type;this.data = new HashMap<>();}public void putData(String column, Object value) {data.put(column, value);}public String toJSON() {// 将 RowMap 转换为 JSON 字符串}
}
在 RowMap
中:
database
和table
表示数据变更的数据库和表。type
表示操作类型(INSERT、UPDATE、DELETE)。data
是存储行变化数据的键值对映射(列名 -> 值)。
3.4 Producer
(事件发布器)
Producer
负责将处理好的事件(即 RowMap
)发送到外部系统,如 Kafka 或 Kinesis。Maxwell 提供了多种 Producer 实现,用户可以选择适合自己需求的 Producer。
public class KafkaProducer extends AbstractProducer {private org.apache.kafka.clients.producer.KafkaProducer<String, String> kafkaProducer;public KafkaProducer(MaxwellContext context) {Properties props = new Properties();props.put("bootstrap.servers", context.getConfig().kafkaBootstrapServers);this.kafkaProducer = new org.apache.kafka.clients.producer.KafkaProducer<>(props);}@Overridepublic void push(RowMap r) {String topic = getKafkaTopic(r);String key = r.getPrimaryKey();String value = r.toJSON();kafkaProducer.send(new ProducerRecord<>(topic, key, value));}
}
在 KafkaProducer
中:
push
方法将RowMap
对象转换为 JSON 格式,并发送到指定的 Kafka topic。
4. Maxwell 高级特性
-
Schema 变更捕获:Maxwell 也能够捕捉 MySQL 表结构的变化(如
ALTER TABLE
),它维护了一份 schema 的缓存,以便解析 binlog 事件时能够正确映射列与值。 -
断点续传:Maxwell 记录并维护 binlog 的位置,当服务重启或崩溃时,能够从上次停止的位置继续读取,不会丢失任何数据。
-
过滤:Maxwell 支持基于数据库和表的过滤,用户可以通过配置文件或命令行参数来指定需要捕获或忽略的数据库和表。
-
事务处理:Maxwell 通过 binlog 的事务边界来确保事件的顺序性和一致性,保证在输出端(如 Kafka)消费时,数据的顺序与数据库中的顺序一致。
总结
Maxwell 是一个轻量级的 MySQL binlog 解析工具,它通过 BinlogConnectorReplicator
连接 MySQL 并获取 binlog 数据,利用 BinlogParser
解析这些二进制日志,将其转化为易于处理的 RowMap
对象,并通过 Producer
发送到外部系统。Maxwell 提供了灵活的输出方式和良好的容错机制,适用于实时数据同步和流式数据处理场景。
相关文章:

Maxwell 底层原理 详解
Maxwell 是一个 MySQL 数据库的增量数据捕获(CDC, Change Data Capture)工具,它通过读取 MySQL 的 binlog(Binary Log)来捕获数据变化,并将这些变化实时地发送到如 Kafka、Kinesis、RabbitMQ 或其他输出端。…...

使用短效IP池的优势是什么?
短效IP池作为代理IP服务中一种独特的资源管理方式,其应用已经在数据采集、市场分析和网络安全等多个领域中展示出强大的功能。尽管“短效”听起来似乎意味着某种限制,然而在某些特定的应用场景下,短效IP池却提供了无可比拟的优势。本文将详细…...

zynq烧写程序到flash后不运行
🏆本文收录于《全栈Bug调优(实战版)》专栏,主要记录项目实战过程中所遇到的Bug或因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&am…...

JMeter如何设置HTTP代理服务器?
1、 2、添加线程组 3、设置HTTP代理服务器,目标控制器选择“测试计划>线程组” 过滤掉不需要的信息 4、设置电脑手动代理 5、点击启动,在浏览器操作就可以了...

React面试题笔记(一)
一、react基础面试题 1.react中keys的作用是什么? key是是用于追踪哪些列表被修改,被添加或者被移除的辅助标识。 在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是…...

3.Java入门笔记--基础语法
1.字面量 概念:计算机用来处理数据的,字面量就是告诉程序员数据在程序中的书写格式 常用数据:整数,小数直接写;字符单引号(A)且只能放一个字符;字符串双引号("Hel…...

关于SOCKS协议的常见误区有哪些?
代理协议在设备与代理服务器之间的数据交换中起到了关键作用。在这方面,SOCKS代理协议是常见的选择之一,被广泛应用于下载、传输和上传网络数据的场景。然而,关于SOCKS代理协议存在一些常见的误解,让我们来逐一了解。 一、使用SO…...

无极低码课程【redis windows下服务注册密码修改】
下载Windows版本的Redis linux环境 (自行下载) 1.打开官网https://redis.io/downloads/ windows环境 1.打开github https://github.com/microsoftarchive/redis/releases 然后选择你喜欢的版本zip或msi下载 2.这里下载zip版,解压后后,打开安装目录 3.双击redis-server…...

多ip访问多网站
1,关闭防火墙和安全软件 [rootlocalhost ~]# systemctl stop firewalld.service [rootlocalhost ~]# setenforce 02,挂载点,下载nginx [rootlocalhost ~]# mount /dev/sr0 /mnt [rootlocalhost ~]# dnf install nginx -y 3,一个虚拟机增加多个ip地址 [rootloc…...

Pytest参数详解 — 基于命令行模式!
1、--collect-only 查看在给定的配置下哪些测试用例会被执行 2、-k 使用表达式来指定希望运行的测试用例。如果测试名是唯一的或者多个测试名的前缀或者后缀相同,可以使用表达式来快速定位,例如: 命令行-k参数.png 3、-m 标记(…...

指针——函数指针数组
(一)前文回顾 1、前篇代码分析 void(*signal(int , void(*)(int)))(int) ; 那么这串代码究竟是什么呢? 别慌,让我们来一步一步拆解,首先我们通过之前的学习,已经明白了什么是函数指针(如果有…...

MySQL中的增查操作:探索数据的奥秘,开启数据之门
本节,我们继续深入了解MySQL,本章所讲的基础操作,针对的是表的增删查改! 一、Create 新增 1.1、语法 INSERT [INTO] table_name[(column [, column] ...)] VALUES(value_list) [, (value_list)] ... value_list: value, [, va…...

oracle_查询建表语句
查询建表语句 SELECTdbms_metadata.get_ddl ( TABLE, <table_name> ) FROMdualdbms_metadata.get_ddl:是Oracle提供的一个函数,用于获取数据库对象的DDL语句,它允许你查看或导出数据库对象的创建脚本‘TABLE’: 是这个函数…...

004-按照指定功能模块名称分组
按照指定功能模块名称分组 一、说明1.现在有一个需求:2.具体做法 二、代码案例三、效果展示 一、说明 1.现在有一个需求: 需要把一个功能模块的几个功能点放在同一个文档目录下,这几个功能点分布在不同的 Controller 2.具体做法 需要把他…...

ChatGPT写作助手:论文写作必备提示词一览
学境思源,一键生成论文初稿: AcademicIdeas - 学境思源AI论文写作 随着人工智能技术的发展,ChatGPT在学术写作领域的应用越来越广泛。它不仅能够帮助撰写论文,还可以通过不同的提示词完成构思、文献综述、数据分析、润色等任务&a…...

大数据开发电脑千元配置清单
大数据开发电脑配置清单 电脑型号HUANANZHI 台式电脑操作系统Windows 11 专业版 64位(Version 23H2 / DirectX 12)处理器英特尔 Xeon(至强) E5-2673 v3 2.40GHz主板HUANANZHI X99-P4T(P55 芯片组)显卡NVIDIA GeForce GT 610 ( 2…...

VP9官方手册-帧内预测
8.5.1 intra prediction process...

windows 自定义scheme协议。
浏览器打开自定义scheme参考上一篇:Chromium 自定义scheme协议启动过程分析c 1、注册表里面按照如下格式填写自定义scheme协议导入: Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\jdtest] "URL:jdtest Protocol" "URL Proto…...

什么是SQLite?
一、什么是SQLite? SQLite是一个进程内的软件库,实现了自给自足的、无服务器的、零配置的、事务性的SQL数据库引擎。它是一个零配置的数据库,这意味着与其他数据库不一样,您不需要在系统中配置。 就像其它数据库,SQLite引擎不是…...

域1:安全与风险管理 第2章-人员安全与风险管理
第二章的内容确实较为丰富,需要细心且耐心地逐步消化和理解。不妨放慢阅读速度,对每个要点都进行深入思考,确保自己真正掌握了其核心意义。这样,虽然可能花费更多时间,但能够更扎实地掌握第二章的知识,为后…...

php中的错误和异常捕获
目录 一: 异常(Exceptions) 二: 错误(Errors) 三:实际项目的异常和错误处理 在PHP中,异常(Exceptions)和错误(Errors)是两个不同的…...

nextjs项目中,使用postgres的完整案例
目的 通过此案例,可以简单快速的过一下数据库的操作,熟悉app-router这种模式下,client component和server component的两种组件中基本的接口使用。 技术栈 nextjs14.2.* app-routervercel/postgres0.10.*typescript5 重要事情说三遍1 ap…...

tsconfig.json 内容解读
tsconfig.json 文件是 TypeScript 项目的主要配置文件,用于指定编译选项和项目设置。通过这个文件,你可以控制编译器的行为,例如输出文件的路径、模块解析方式、严格类型检查等。 以下是一些常见的 tsconfig.json 属性及其详细解释ÿ…...

KClass-关于kotlin中的反射
override val responseType: KClass<SetOperationModeResponse> SetOperationModeResponse::class,这段代码的含义: responseType 是一个只读属性(val),它的类型是 KClass<SetOperationModeResponse>。KClass<T&…...

Java集合剖析2】Java集合底层常用数据结构
一、数据结构与集合 接下来就要学习集合具体的实现类了,集合的实现类底层可能用1种或多种数据结构来存储数据。所以在学习集合的实现类前,我们有必要了解一下一些常见的数据结构,这样我们在后面查看集合实现类的底层源码时,才不会…...

java 第10天 String创建以及各类常用方法
一.String创建的两种形式 1.通过new的当时 String strnew String(); 2.不new的方式 String s1""; 二.new 和不new的方式的区别是什么 不new创建的字符串首先是拿着值去常量池中查找,是否有该内容,有就用常量池该字符串的地址࿰…...

VS 解决方案里面.vs文件夹
VS解决方案中的.vs文件夹主要用于存储当前用户在解决方案中的工作配置。 这些配置包括多个方面: 窗口布局和选项卡状态:.vs文件夹记录了VS关闭前最后的窗口布局以及最后打开的选项卡。这样,当用户重新打开解决方案时,可以继续之前…...

初试PostgreSQL数据库
文章目录 一、PostgreSQL数据库概述1.1 PostgreSQL的历史1.2 PostgreSQL安装1.3 安装PostgreSQL二、PostgreSQL起步2.1 连接数据库2.1.1 SQL Shell2.1.2 执行SQL语句2.2 pgAdmin 42.2.1 打开pgAdmin 42.2.2 查找数据库2.2.3 打开查询工具2.2.4 执行SQL语句三、实战小结文章目录…...

springboot3导出数据库数据到excel
一、导入依赖 <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.3.0</version></dependency><d…...

十四、行为型(观察者模式)
观察者模式(Observer Pattern) 概念 观察者模式(Observer Pattern)是一种行为型设计模式,它定义了对象间的一对多依赖关系,当被观察的对象(主题)状态发生改变时,所有依赖…...