百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Canal binlog 日志 Dump 流程分析

toyiye 2024-07-06 00:25 22 浏览 0 评论

Canal 的 dump 支持串行和并行模式两种模式,本篇重点梳理 dump 的核心流程,以便对 dump 过程有一个充分的了解,更好的理解 Canal 的实现原理与细节,下一篇中将重点关注Canal是如何引入并行模式来提高dump的性能,即并行编程相关的技巧。

从前面的文章我们得知 Canal binlog 日志解析的基本流程如下图所示:

解析来重点梳理一下 dump 命令的发送逻辑,特别是日志的处理流程,一些基本的日志格式。

1、 dump 流程分析

在 Canal 中 dump 方法声明如下:

带有参数 MultiStageCoprocessor 为并行处理模式,底层使用了disruptor 高性能并发框架,下文将重点关注学习。我们今天重点来看一下串行dump的实现,其方法声明如下:

其方法参数说明如下:

  • String binlogfilename
    binlog 文件名称,例如 mysql-bin.000038。
  • Long binlogPosition
    在文件中的偏移量。
  • SinkFunction func
    每解析出一条binlog日志的处理函数。

接下来我们直奔主题,一起来看一下 MysqlConnection 关于 dump 的实现流程。


Step1:在发送dump之前先设置相关的参数。

  • set wait_timeout=9999999
    连接空闲超时时间,默认为8消息,用于 Canal Slave 的等待超时时间远大于默认值。
  • set net_write_timeout=1800
    网络写请求超时时间,针对正在进行数据读写的连接,该值默认为 60s。
  • set net_read_timeout=1800
    网络读请求超时时间,针对正在进行数据读写的连接,该值默认为 30s。
  • set names 'binary'
    设置服务端返回结果时不做编码转化,直接按照数据库的二进制编码进行发送,由客户端自己根据需求进行编码转化。
  • set @master_binlog_checksum= @@global.binlog_checksum
    设置master_binlog_checksum,因为在mysql5.6之后为binlog引入了checksum机制,例如crc32,canal作为mysql slave,需要与服务端相关参数保持一致。
  • set @slave_uuid=uuid()
    canal相对与mysql数据库服务而言就是一个从服务器,这个指令用于设置server_id,使用uuid,避免server_id重复。
  • SET @master_heartbeat_period=15
    设置客户端与服务端心跳发送间隔,默认为15s。

Step2:从主库查询binlog checksum,具体向主库发送 select @@global.binlog_checksum 语句。

Step3:向MySQL Master 注册从节点,告知客户端的host、port、用户名与密码、serverId,具体实现是发送命令CODE为 0x15。

Step4:向 MySQL Master 发送 dump 请求,MySQL是基于请求与应答模式,发送请求命令后,就会向网络通道中写入响应请求。(在这里大家不妨先大概思考一下如何读取 dump 命令的返回值,这部分虽然涉及到网络相关的知识,我在这边会稍微简单提一下)。

Step5:构建 DirectLogFetcher对象,实现基于 socket 的日志拉取服务,并构建 LogDecoder 对象,用于解析 binlog 日志。

Step6:使用 while 循环反复拉取消息,通过通过 LogDecoder 对二进制流进行解析,提取一条完整的binlog事件,交给 SinkFunction 去处理,并且如果开启了半同步机制,则需要向master发送ACK。既然是while循环,该方法的退出条件还是值得我们关注的:

  • fetch.fetch()方法返回 false
  • SinkFunction 的 sink 方法 false,SinkFunction的详细处理流程将在下文介绍,这里先告知返回false的情况是 binlog 日志解析线程已停止运行。

上面粗略的介绍了 dump 命令的几个核心关键步骤,要想详细掌握其实现细节,我们必须继续深入探讨如下几个问题:

  • DirectLogFetcher 内部工作机制
  • LogDecoder binlog 日志解析
  • 发送Dump底层网实现思路

2、DirectLogFetcher 内部工作机制

2.1 DirectLogFetcher 类图

DirectLogFetcher的类继承体系如上图所示,我们来看一下其关键点:

  • LogBuffer
    日志buffer,主要定义如下属性:
    • byte[] buffer
      缓存区中数据容器。
    • int origin
      当前buffer中的读指针
    • int limit
      当前buffer的最大可读可写指针
    • int position
      当前buffer的写指针。
    • int semival
      是否需要发送ACK(用于半同步)。
      LogBuffer封装了字节相关的操作,不仅定义了上面的属性,也定义了字节读取相关众多API,其截图如下:
  • LogFetcher
    binlog日志抓取抽象类,定义了如下关键属性与抽象方法。
  • int DEFAULT_INITIAL_CAPACITY
    LogBuffer中的初始容量,默认为8K。
  • float DEFAULT_GROWTH_FACTOR
    容量增长因子,默认为 2.0。
    • int BIN_LOG_HEADER_SIZE
      binlog日志条目 header 的长度,固定为4字节。
    • float factor
      增长因子。
    • public abstract boolean fetch()
      抓取binlog日志。
    • public abstract void close()
      关闭 Fetch。
  • DirectLogFetcher
    Canal LogFetcher模式实现类,其核心属性如下:
  • SocketChannel channel
    网络通道,用于发送dump请求的网络通道。
  • boolean issemi = false
    是否开启半同步。

2.2 fetch流程详解

接下来我们重点剖析 DirectLogFetcher 的 fetch 方法,来探究其实现原理。

在研究DirectLogFetcher的fetch方法之前,我们先重点跟踪一下其内部网络读写方法fetch0方法,该方法是具体与网络读写相关的实现。

在详细介绍该方法之前先来介绍一下其参数的含义:

  • int off
    从通道中读取到的内容放入到buffer中的起始位置
  • int len
    期望从通道中读取的字节长度。

该方法的实现关键点如下:

  • 首先先确保接收缓存区有足够的剩余空间,如果空间不足,则进行扩容。
  • 然后从通道中读取指定长度的字节。

接下来我们来重点看一下DirectLogFetcher的fetch的实现流程。

Step1:尝试从网络通道中读取4个字节(即读取协议的头部),如果通道中还没有可读取内容,返回false,造成的效果是一次 dump 请求结束。

Step2:从上文读到的4个字节分别读出该网络包的总长度以及当前包的序号,从这里可以看成MySQL协议头为4字节,前3个字节为网络包的总长度,第4个字节为包的序列号。再取出数据包的长度后,继续向通道中读取netlen个字节,即读取一个完整的数据包到buffer中。

Step3:继续从数据包中读取一个字节,判断该包的状态码,是否是一个成功的响应,如果是错误的响应,会向外抛出一次,Canal 会记录dump命令执行错误的次数。

Step4:如果一个包的长度为允许的最大包长度,则继续读取,这个主要是根据MySQL协议做的处理,即读取到一个数据包,然后返回true,表示拉取到一条日志,然后通过LogDecoder解码,然后传入到sink方法中,进行日志的后续处理。

Step5:这一步的目的,就是将buffer中的当前指针指向数据的开始位置。

这样一次 fetch就结束了。

从上面的流程来看,DirectLogFetcher#fetch 方法结束后,就将进入到LogDecoder中。经过一次DirectLogFetcher#fetch方法后,即取回一条binlog日志,即二进制流,接下来就根据binlog协议对其解析。本文暂不深入该方法,如果大家想深入数据库中间件方面,可以作为一个很好的示例,面向MySQL通信协议进行编程。


3、SinkFunction

通过 LogDecoder从中解析一个事件后,会调用SinkFunction的sink方法,如果该方法返回 false,一次dump请求将介绍,接下来我们看一下其sink方法。

该方法的实现比较简单,这里不打算继续深入,我们重点来看一下 Canal.Entry 的结构:

这个结构是基于Canal做架构设计,解决顺序消费、数据不丢失一个重要参考依据,没解析一条事务,最终放入到环形缓存区,环形缓存区尽量以一个事务提交到Sink组件,其代码如下:

这里主要有如下几个关键点:

  • 首先需要调用EventSink组件将解析出来的数据传入EventSink。
  • EventSink组件处理成功后,会提交解析位点。

本文就介绍到这里了,本文是Canal系列的第7篇,三联(点赞、转发、评论)是对我最大的认可与鼓励,谢谢。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码