前言

前面的文章里,我们了解到 canal 可以从 MySQL 中感知数据的变化。这是因为它模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,从而实现了主从复制。

正是了解到这一点,笔者有两个问题便一直萦绕于心:

它是如何模拟 MySQL slave 交互协议的?

它又是怎么解析 binlog 日志的呢?

今天,笔者准备就着这两个问题,扒拉扒拉 canal 的代码,一探究竟。

一、MySQL 主从复制

在谈 canal 之前,我们有必要再重温下 MySQL 主从复制的原理。

总结上图的流程如下:

MySQL master 将数据变更写入二进制日志 (binary log , 其中记录叫做二进制日志事件binary log events);

MySQL slave 将 master 的 binary log events 拷贝到它的中继日志 (relay log);

MySQL slave 重放 relay log 中的事件,将数据变更反映到自己的数据库。

二、canal 原理

上图就很形象的描述了 canal 的角色。它的原理也很简单:

canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议;

mysql master收到dump请求,开始推送binary log给slave(也就是canal);

canal解析binary log对象(原始为byte流);

canal将解析后的对象,根据业务场景,分发到比如 MySQL 、RocketMQ 或者 ES 中。

三、源码启动

看完了 MySQL 主从复制和 canal 原理之后,为了方便 debug ,笔者已经在 GitHub Fork 了源码,并导入本地。

可以找到 com.alibaba.otter.canal.deployer.CanalLauncher 类,它就是 canal 独立版本启动的入口类。

在这里,直接运行 main 方法即可运行 canal ,和在 /canal/bin/startup.sh 中效果一样。

事实上,canal 的代码比较多,在架构上又分了很多模块设计,比如事件解析器、事件消费、内存存储、服务实例、元数据、高可用等。

本文不打算面面俱到介绍每一个的实现,那就得正儿八经写一个 canal 系列才行。主要还是为了开头我们提出的那两个问题。

四、如何模拟slave ?

上面我们已经说到,CanalLauncher是canal 启动的入口类。

运行 main 方法之后, canal 会先做很多准备工作。比如加载配置文件、初始化消息队列、启动 canal Admin、加载Spring配置、注册钩子程序等。

canal 模拟 slave 协议,是在EventParser模块中开始进行的。

在 canal 代码中,整个流程简化如下:

// 开始执行replication

// 1. 构造Erosa连接

ErosaConnection erosaConnection = buildErosaConnection();

// 2. 启动一个心跳线程

startHeartBeat(erosaConnection);

// 3. 执行dump前的准备工作

preDump(erosaConnection);

erosaConnection.connect();// 链接

// 查询master serverId

long queryServerId = erosaConnection.queryServerId();

if (queryServerId != 0) {

serverId = queryServerId;

}

// 4. 获取binlog最后的位置信息

EntryPosition position = findStartPosition(erosaConnection);

final EntryPosition startPosition = position;

// 加载元数据

processTableMeta(startPosition);

// 重新链接,因为在找position过程中可能有状态,需要断开后重建

erosaConnection.reconnect();

// 4. 开始dump数据

erosaConnection.dump(startPosition.getJournalName(),startPosition.getPosition(),sinkHandler);

复制代码

1、握手、验证

在开始之前,canal 必须先要和 MySQL 服务器建立连接,并完成客户端身份验证。

在 MySQL 中,连接过程协议如下:

在代码中,我们看一下它的连接方法:

其中,negotiate方法是握手协议和客户端验证的具体实现。就是按照 MySQL 的协议规范,通过上面创建的Socket channel来读写网络数据。

2、dump前的准备

正确连接到 MySQL 后,在开始执行 dump 指令之前,还要初始化一些配置信息。

思路就是通过 MySQL 执行器,执行 SQL 语句,获取信息。

代码就不粘了,不过它们执行的语句如下:

show variables like 'binlog_format' #获取binlog format格式

show variables like 'binlog_row_image' #获取binlog image格式

show variables like 'server_id' #获取matser serverId

show master status #获取binlog名称和position

复制代码

3、注册slave

现在开始调用 erosaConnection.dump(binlogfilename,binlogPosition,func)方法,来注册slave和发送dump命令。

在使用COM_BINLOG_DUMP请求binlog事件之前发送,在主服务器上注册一个从服务器,它的指令是COM_REGISTER_SLAVE。

注册完之后,就是发送dump请求,它的指令是COM_BINLOG_DUMP。

在执行完这段代码后,我们通过show processlist;查看进程,就可以看到这个dump线程的状态。

id

user

host

db

command

time

state

139

canal

localhost:62901

null

Binlog Dump

3

Master has sent all binlog to slave; waiting for more updates

五、如何解析binlog数据 ?

在上面章节中,我们已经看到,MySQL主服务器已经接受了 canal 这个从服务器,那么当canal拿到binlog内容后, 又是怎么解析它的呢?

首先,还记得在配置MySQL服务器的时候,我们将binlog-format设置为ROW模式,它是基于行的复制。

binlog中每一个数据变更可以叫做事件,在ROW模式下,有几个主要的事件类型:

事件

SQL命令

rows 内容

TABLE_MAP_EVENT

null

定义将要更改的表。

WRITE_ROWS_EVENT

插入

要插入的行数据

DELETE_ROWS_EVENT

删除

被删除的数据

UPDATE_ROWS_EVENT

更新

原数据+要更改的数据

每一次数据的变更,都会触发2个事件,先把要更改的表信息告诉你,然后再告诉你更改的row内容。

比如TABLE_MAP_EVENT + WRITE_ROWS_EVENT。

canal在接收到binlog数据后,并不会马上把它解析成我们熟悉的JSON数据,而是在发送的时候才开始。

比如我们选择使用RocketMQ,那么在发送之前才开始将binlog里面的byte数组转化为对象。

// 并发构造

EntryRowData[] datas = MQMessageUtils.buildMessageData(message, executor);

// 串行分区

List flatMessages = MQMessageUtils.messageConverter(datas, message.getId());

复制代码

在这两个方法里,就完成了byte数组到对象的转化。转化成的FlatMessage对象,就成了我们在消息队列中消费到的数据结构。

public class FlatMessage implements Serializable {

private long id;

private String database;

private String table;

private List pkNames;

private Boolean isDdl;

private String type;

// binlog executeTime

private Long es;

// dml build timeStamp

private Long ts;

private String sql;

private Map sqlType;

private Map mysqlType;

private List> data;

private List> old;

}

复制代码

总结

正如本文开头所言,笔者在刚了解到canal机制的时候,确实觉得很不可思议。

咦,它是怎么模拟MySQL slave的呢 ? 总觉得是不是有啥黑科技在里面。。。

事实上,这是源于笔者对MySQL的无知。

MySQL早就制定好了各种接口协议,怎么连接、验证、注册和dump都明明白白的写在那儿啦。

正是应了那句话:花开正好,只待君来~

mysql主从和canal_MySQL协议和canal实现相关推荐

  1. MySQL协议和canal实现

    前言 前面的文章里,我们了解到 canal 可以从 MySQL 中感知数据的变化.这是因为它模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,从而实现了主从复制. 正是了 ...

  2. erosa mysql_MySQL协议和canal实现

    前言 前面的文章里,我们了解到 canal 可以从 MySQL 中感知数据的变化.这是因为它模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,从而实现了主从复制. 正是了 ...

  3. 一文讲清,MySQL主从架构

    MySQL在生成环境中,如果是单机版的部署方式,就会有很大的可用性问题,MySQL提供了一套主从复制的架构,以提高其可用性. MySQL主从复制架构,就是部署两台机器,一台机器上部署的MySQL是ma ...

  4. MySQL 主从同步延迟的原因及解决办法

    首页 博客 专栏·视频 下载 论坛 问答 代码 直播 能力认证 高校 会员中心 收藏 动态 消息 创作中心 MySQL 主从同步延迟的原因及解决办法 hao_yunfeng 2018-09-04 23 ...

  5. MySQL主从架构、读写分离、集群相关面试问题

    文章目录 一.MySQL主从同步原理 二.MySQL主从集群面试相关问题 1.全库同步与部分同步 2.GTID同步集群 3.集群扩容与MySQL数据迁移 4.理解半同步复制 5.主从集群与读写分离 6 ...

  6. mysql主从库配置ps:mysql5.6

    1 Mysql cluster版本主从服务器搭建实践 主从的作用:MySQL的主从服务器可以满足同步数据库,同步表,同步表内容,也可以指定仅同步某个数据库或某个表,还可以排除不同步某个数据库某个表. ...

  7. 高性能Mysql主从架构的复制原理及配置详解

    1 复制概述 Mysql内建的复制功能是构建大型,高性能应用程序的基础.将Mysql的数据分布到多个系统上去,这种分布的机制,是通过将Mysql的某一台主机的数据复制到其它主机(slaves)上,并重 ...

  8. mysql查询并设置高亮_Thinkphp3.2.3设置MySql主从读写分离后,简单调用主数据库查询

    图/文:迷神 Thinkphp是一款不错的国产框架,使用范围广,应用也比较多.随着网站访问增大往往需要使用mysql主从同步功能,本身Thinkphp自带了主从读写分离的功能了. 但是我们经常有一个场 ...

  9. mysql主从数据库含义_(转)Mysql数据库主从心得整理

    管理mysql主从有2年多了,管理过200多组mysql主从,几乎涉及到各个版本的主从,本博文属于总结性的,有一部分是摘自网络,大部分是根据自己管理的心得和经验所写,整理了一下,分享给各位同行,希望对 ...

最新文章

  1. 第六章 深度学习(上中)
  2. 百度地图api应用程序大赛作品
  3. boost::hana::typeid_用法的测试程序
  4. 解决iview表单中时间选择起的验证失败问题
  5. # 20175311 2018-2019-2 《Java程序设计》第2周学习总结
  6. Git学习总结(18)——让你成为Git和GitHub大神的20个技巧
  7. 预充电电路工作原理_变频冰箱开关电源电路工作原理及检修。
  8. 多文件上传组件FineUploader使用心得
  9. java ftc 68是什么意思_机器人比赛;FTC项目介绍与院校简介
  10. python企业微信群聊_python调用企业微信接口发送群聊消息代码参考
  11. 一个Query Builder,征集更好用的Query Builder的设计方案
  12. r语言熵权法求权重(真实案例完整流程)
  13. 那些被苏宁奖励的人、重用的人
  14. 浅谈CFD(constant fraction discriminator恒比鉴相器)
  15. 大学计算机组织部面试问题及答案,组织部面试问题及答案(30页)-原创力文档...
  16. 三种设计满足需求 网吧网络解决方案(转)
  17. 百度滴滴京东实习生面试题
  18. 教孩子学习乘法和除法,我算是绞尽脑汁了
  19. 关于 YCbCr(YUV) 格式视频流的介绍
  20. Ubuntu下如何查看GPU版本和使用信息?

热门文章

  1. 湖南大学21夏训练四11.蛇形矩阵
  2. Python-inspect的使用
  3. linux中 samba服务器配置,linux下samba服务器安装配置方法
  4. c语言中求一个3x3的整形矩阵,编程实现求两个3x3矩阵的和(C语言)
  5. JSP+ssm计算机毕业设计奥迪汽车配件网络销售系统8avr0【源码、数据库、LW、部署】
  6. 关于分布式锁的续命问题——基于Redis实现的分布式锁
  7. 普通人如何快速赚得人生的第一个100万?
  8. OOM(内存溢出)造成原因及解决方案
  9. 北京信息科技大学Linux,北京信息科技大学Linux实验报告3
  10. Xceed Ultimate Suite 2022.2