Java最全Canal binlog 日志 Dump 流程分析,java基础面试

总结

其他的内容都可以按照路线图里面整理出来的知识点逐一去熟悉,学习,消化,不建议你去看书学习,最好是多看一些视频,把不懂地方反复看,学习了一节视频内容第二天一定要去复习,并总结成思维导图,形成树状知识网络结构,方便日后复习。

这里还有一份很不错的《Java基础核心总结笔记》,特意跟大家分享出来

目录:

部分内容截图:

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

设置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。

MysqlConnection#dump

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

MysqlConnection#dump

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

MysqlConnection#dump

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

MysqlConnection#dump

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

MysqlConnection#dump

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方法,该方法是具体与网络读写相关的实现。

DirectLogFetcher#fetch0

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

  • int off

从通道中读取到的内容放入到buffer中的起始位置

  • int len

期望从通道中读取的字节长度。

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

  • 首先先确保接收缓存区有足够的剩余空间,如果空间不足,则进行扩容。

  • 然后从通道中读取指定长度的字节。

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

DirectLogFetcher#fetch

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

DirectLogFetcher#fetch

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

DirectLogFetcher#fetch

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

DirectLogFetcher#fetch

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

DirectLogFetcher#fetch

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

最后

针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。

最新整理面试题
在这里插入图片描述

上述的面试题答案都整理成文档笔记。也还整理了一些面试资料&最新2021收集的一些大厂的面试真题

最新整理电子书

在这里插入图片描述

最新整理大厂面试文档

在这里插入图片描述

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

有所帮助,也希望大家多多支持。

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值