关于mysql:Materialize-MySQL引擎MySQL到Click-House的高速公路

9次阅读

共计 4565 个字符,预计需要花费 12 分钟才能阅读完成。

摘要:MySQL 到 ClickHouse 数据同步原理及实际

引言

相熟 MySQL 的敌人应该都晓得,MySQL 集群主从间数据同步机制非常欠缺。令人惊喜的是,ClickHouse 作为近年来煊赫一时的大数据分析引擎也能够挂载为 MySQL 的从库,作为 MySQL 的 “ 协处理器 ” 面向 OLAP 场景提供高效数据分析能力。新近的计划比拟含糊其辞,通过第三方插件将所有 MySQL 上执行的操作进行转化,而后在 ClickHouse 端逐个回放达到数据同步。终于在 2020 年下半年,Yandex 公司在 ClickHouse 社区公布了 MaterializeMySQL 引擎,反对从 MySQL 全量及增量实时数据同步。MaterializeMySQL 引擎目前反对 MySQL 5.6/5.7/8.0 版本,兼容 Delete/Update 语句,及大部分罕用的 DDL 操作。

根底概念

  • MySQL & ClickHouse

MySQL 个别特指残缺的 MySQL RDBMS,是开源的关系型数据库管理系统,目前属于 Oracle 公司。MySQL 凭借不断完善的性能以及沉闷的开源社区,吸引了越来越多的企业和个人用户。

ClickHouse 是由 Yandex 公司开源的面向 OLAP 场景的分布式列式数据库。ClickHouse 具备实时查问,残缺的 DBMS 及高效数据压缩,反对批量更新及高可用。此外,ClickHouse 还较好地兼容 SQL 语法并领有开箱即用等诸多长处。

  • Row Store & Column Store

MySQL 存储采纳的是 Row Store,表中数据依照 Row 为逻辑存储单元在存储介质中间断存储。这种存储形式适宜随机的增删改查操作,对于按行查问较为敌对。但如果抉择查问的指标只波及一行中少数几个属性,Row 存储形式也不得不将所有行全副遍历再筛选出指标属性,当表属性较多时查问效率通常较低。只管索引以及缓存等优化计划在 OLTP 场景中可能晋升肯定的效率,但在面对海量数据背景的 OLAP 场景就显得有些力不从心了。

ClickHouse 则采纳的是 Column Store,表中数据依照 Column 为逻辑存储单元在存储介质中间断存储。这种存储形式适宜采纳 SIMD (Single Instruction Multiple Data) 并发解决数据,尤其在表属性较多时查问效率显著晋升。列存形式中物理相邻的数据类型通常雷同,因而人造适宜数据压缩从而达到极致的数据压缩比。

应用办法

  • 部署 Master-MySQL

开启 BinLog 性能:ROW 模式
开启 GTID 模式:解决位点同步时 MySQL 主从切换问题(BinLog reset 导致位点生效)

  • 部署 Slave-ClickHouse

获取 ClickHouse/Master 代码编译装置
举荐应用 GCC-10.2.0,CMake 3.15,ninja1.9.0 及以上

  • 创立 Master-MySQL 中 database 及 table

  • 创立 Slave-ClickHouse 中 MaterializeMySQL database

此时能够看到 ClickHouse 中曾经有从 MySQL 中同步的数据了:

工作原理

  • BinLog Event

MySQL 中 BinLog Event 次要蕴含以下几类:

事务提交后,MySQL 将执行过的 SQL 解决 BinLog Event,并长久化到 BinLog 文件

ClickHouse 通过生产 BinLog 达到数据同步,过程中次要思考3个方面问题:

1、DDL 兼容:因为 ClickHouse 和 MySQL 的数据类型定义有区别,DDL 语句须要做相应转换

2、Delete/Update 反对:引入 _version 字段,管制版本信息

3、Query 过滤:引入 _sign 字段,标记数据有效性

  • DDL 操作

比照一下 MySQL 的 DDL 语句以及在 ClickHouse 端执行的 DDL 语句:

能够看到:

1、在 DDL 转化时默认减少了 2 个暗藏字段:_sign(- 1 删除, 1 写入) 和 _version(数据版本)
2、默认将表引擎设置为 ReplacingMergeTree,以 _version 作为 column version
3、原 DDL 主键字段 runoob_id 作为 ClickHouse 排序键和分区键

此外还有许多 DDL 解决,比方减少列、索引等,相应代码在 Parsers/MySQL 目录下。

  • Delete/Update 操作

Update:

能够看到,ClickHouse 数据也实时同步了更新操作。

  • Delete:

能够看到,删除 id 为 2 的行只是额定插入了 _sign == -1 的一行记录,并没有真正删掉。

  • 日志回放

MySQL 主从间数据同步时 Slave 节点将 BinLog Event 转换成相应的 SQL 语句,Slave 模仿 Master 写入。相似地,传统第三方插件沿用了 MySQL 主从模式的 BinLog 生产计划,行将 Event 解析后转换成 ClickHouse 兼容的 SQL 语句,而后在 ClickHouse 上执行(回放),但整个执行链路较长,通常性能损耗较大。不同的是,MaterializeMySQL 引擎提供的外部数据解析以及回写计划隐去了三方插件的简单链路。回放时将 BinLog Event 转换成底层 Block 构造,而后间接写入底层存储引擎,靠近于物理复制。此计划能够类比于将 BinLog Event 间接回放到 InnoDB 的 Page 中。

同步策略

  • 日志回放

v20.9.1 版本前是基于位点同步的,ClickHouse 每生产完一批 BinLog Event,就会记录 Event 的位点信息到 .metadata 文件:

这样当 ClickHouse 再次启动时,它会把 {‘mysql-bin.000003’, 355005999} 二元组通过协定告知 MySQL Server,MySQL 从这个位点开始发送数据:

存在问题:

如果 MySQL Server 是一个集群,通过 VIP 对外服务,MaterializeMySQL 创立 database 时 host 指向的是 VIP,当集群主从产生切换后,{Binlog File, Binlog Position} 二元组不肯定是精确的,因为 BinLog 能够做 reset 操作。

为了解决这个问题,v20.9.1 版本后上线了 GTID 同步模式,废除了不平安的位点同步模式。

  • GTID 同步

GTID 模式为每个 event 调配一个全局惟一 ID 和序号,间接告知 MySQL 这个 GTID 即可,于是 .metadata 变为:

其中 0857c24e-4755-11eb-888c-00155dfbdec7 是生成 Event 的主机 UUID,1-783 是曾经同步的 event 区间

于是流程变为:

源码剖析

  • 概述

在最新源码 (v20.13.1.1) 中,ClickHouse 官网对 DatabaseMaterializeMySQL 引擎的相干源码进行了重构,并适配了 GTID 同步模式。ClickHouse 整个我的项目的入口 main 函数在 /ClickHouse/programs/main.cpp 文件中,主程序会依据接管指令将工作散发到 ClickHouse/programs 目录下的子程序中解决。本次剖析次要关注 Server 端 MaterializeMySQL 引擎的工作流程。

  • 源码目录

与 MaterializeMySQL 相干的次要源码门路:

  • 服务端次要流程

ClickHouse 应用 POCO 网络库解决网络申请,Client 连贯的解决逻辑在 ClickHouse/src/Server/*Handler.cpp 的 hander 办法里。以 TCP 为例,除去握手,初始化上下文以及异样解决等相干代码,次要逻辑能够形象成:

  • 数据同步预处理

Client 发送的 SQL 在 executeQuery 函数解决,次要逻辑简化如下:

次要有三点:

1、解析 SQL 语句并生成语法树 AST
2、InterpreterFactory 工厂类依据 AST 生成执行器
3、interpreter->execute()

跟进第三点,看看 InterpreterCreateQuery 的 excute() 做了什么:

这里正文很显著,次要执行 CREATE 或 ATTACH DATABASE,持续跟进 createDatabase() 函数:

到这里,相当于将工作分发给 DatabaseMaterializeMySQL 解决,接着跟踪 loadStoredObjects 函数:

跟进 startSynchronization() 绑定的执行函数:

  • 全量同步

MaterializeMySQLSyncThread::prepareSynchronized 负责 DDL 和全量同步,次要流程简化如下:

ClickHouse 作为 MySQL 从节点,在 MaterializeMetadata 构造函数中对 MySQL 端进行了一系列预处理:

1、将关上的表敞开,同时对表加上读锁并启动事务
2、TablesCreateQuery 通过 SHOW CREATE TABLE 语句获取 MySQL 端的建表语句
3、获取到建表语句后开释表锁

持续往下走,执行到 metadata.transaction() 函数,该调用传入了匿名函数作为参数,始终跟进该函数会发现最终会执行匿名函数,也就是 cleanOutdatedTables 以及 dumpDataForTables 函数,次要看一下 dumpDataForTables 函数:

持续跟踪 tryToExecuteQuery 函数,会调用到 executeQueryImpl() 函数,上文提到过这个函数,但这次咱们的上下文信息变了,生成的执行器发生变化,此时会进行 DDL 转化以及 dump table 等操作:

此时 InterpreterFactory 返回 InterpreterExternalDDLQuery,跟进去看 execute 函数做了什么:

持续跟进去看看 getIdentifierName(arguments[1])).execute() 做了什么事件:

进一步看 InterpreterImpl::getRewrittenQueries 是怎么转化 DDL 的:

实现 DDL 转换之后就会去执行新的 DDL 语句,实现建表操作,再回到 dumpDataForTables:

  • 增量同步

还记得 startSynchronization() 绑定的执行函数吗?全量同步剖析都是在 prepareSynchronized()进行的,那增量更新呢?

能够看到,while 语句里有一个 binlog_event 的侦听函数,用来侦听 MySQL 端 BinLog 日志变动,一旦 MySQL 端执行相干操作,其 BinLog 日志会更新并触发 binlog_event,增量更新次要在这里进行。

小结

MaterializeMySQL 引擎是 ClickHouse 官网 2020 年主推的个性,因为该个性在生产环境中属于刚需且目前刚上线不久,整个模块处于高速迭代的状态,因而有许多待欠缺的性能。例如复制过程状态查看以及数据的一致性校验等。感兴趣的话可参考 Github 上的 2021-Roadmap,外面会更新一些社区最近得打算。以上内容如有了解谬误还请斧正。

援用

ClickHouse 社区文档

ClickHouse 社区源码

MySQL 实时复制与实现

MaterializeMySQL 引擎剖析

本文分享自华为云社区《MySQL 到 ClickHouse 的高速公路 -MaterializeMySQL 引擎》,原文作者:FavonianKong。

点击关注,第一工夫理解华为云陈腐技术~

正文完
 0