0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

從MySQL到ClickHouse實(shí)時(shí)復(fù)制與實(shí)現(xiàn)

馬哥Linux運(yùn)維 ? 來(lái)源:bohutang.me ? 2023-01-03 10:54 ? 次閱讀

很多人看到標(biāo)題還以為自己走錯(cuò)了夜場(chǎng),其實(shí)沒(méi)有。

ClickHouse 可以掛載為 MySQL 的一個(gè)從庫(kù) ,先全量再增量的實(shí)時(shí)同步 MySQL 數(shù)據(jù),這個(gè)功能可以說(shuō)是今年最亮眼、最剛需的功能,基于它我們可以輕松的打造一套企業(yè)級(jí)解決方案,讓 OLTP 和 OLAP 的融合從此不再頭疼。

目前支持 MySQL 5.6/5.7/8.0 版本,兼容 Delete/Update 語(yǔ)句,及大部分常用的 DDL 操作。

代碼還處于 Alpha 版本階段,畢竟是兩個(gè)異構(gòu)生態(tài)的融合,仍然有不少的工作要做,同時(shí)也期待著社區(qū)用戶的反饋,以加速迭代。

代碼獲取

由于還在驗(yàn)收階段,我們只好把 github 上的 pull request 代碼 pull 到本地。

git fetch origin pull/10851/head:mysql_replica_experiment

開(kāi)始編譯…

MySQL Master

我們需要一個(gè)開(kāi)啟 binlog 的 MySQL 作為 master:

docker run -d -e MYSQL_ROOT_PASSWORD=123 mysql:5.7 mysqld --datadir=/var/lib/mysql --server-id=1 --log-bin=/var/lib/mysql/mysql-bin.log --gtid-mode=ON --enforce-gtid-consistency

創(chuàng)建數(shù)據(jù)庫(kù)和表,并寫入數(shù)據(jù):

mysql> create database ckdb;
mysql> use ckdb;
mysql> create table t1(a int not null primary key, b int);
mysql> insert into t1 values(1,1),(2,2);
mysql> select * from t1;
+---+------+
| a | b    |
+---+------+
| 1 |    1 |
| 2 |    2 |
+---+------+
2 rows in set (0.00 sec)

ClickHouse Slave

目前以 database 為單位進(jìn)行復(fù)制,不同的 database 可以來(lái)自不同的 MySQL master,這樣就可以實(shí)現(xiàn)多個(gè) MySQL 源數(shù)據(jù)同步到一個(gè) ClickHouse 做 OLAP 分析功能。

創(chuàng)建一個(gè)復(fù)制通道:

clickhouse :) CREATE DATABASE ckdb ENGINE = MaterializeMySQL('172.17.0.2:3306', 'ckdb', 'root', '123');
clickhouse :) use ckdb;
clickhouse :) show tables;
┌─name─┐
│ t1   │
└──────┘
clickhouse :) select * from t1;
┌─a─┬─b─┐
│ 1 │ 1 │
└───┴───┘
┌─a─┬─b─┐
│ 2 │ 2 │
└───┴───┘


2 rows in set. Elapsed: 0.017 sec.

看下 ClickHouse 的同步位點(diǎn):
cat ckdatas/metadata/ckdb/.metadata

Version:1
Binlog File:mysql-bin.000001
Binlog Position:913
Data Version:0

Delete

首先在 MySQL Master 上執(zhí)行一個(gè)刪除操作:

mysql> delete from t1 where a=1;
Query OK, 1 row affected (0.01 sec)

然后在 ClickHouse Slave 側(cè)查看記錄:

clickhouse :) select * from t1;


SELECT *
FROM t1


┌─a─┬─b─┐
│ 2 │ 2 │
└───┴───┘


1 rows in set. Elapsed: 0.032 sec.

此時(shí)的 metadata 里 Data Version 已經(jīng)遞增到 2:

cat ckdatas/metadata/ckdb/.metadata
Version:1
Binlog File:mysql-bin.000001
Binlog Position:1171
Data Version:2

Update

MySQL Master:

mysql> select * from t1;
+---+------+
| a | b    |
+---+------+
| 2 |    2 |
+---+------+
1 row in set (0.00 sec)


mysql> update t1 set b=b+1;


mysql> select * from t1;
+---+------+
| a | b    |
+---+------+
| 2 |    3 |
+---+------+
1 row in set (0.00 sec)

ClickHouse Slave:

clickhouse :) select * from t1;


SELECT *
FROM t1


┌─a─┬─b─┐
│ 2 │ 3 │
└───┴───┘


1 rows in set. Elapsed: 0.023 sec.

實(shí)現(xiàn)機(jī)制

在探討機(jī)制之前,首先需要了解下 MySQL 的 binlog event ,主要有以下幾種類型:

1. MYSQL_QUERY_EVENT-- DDL
2. MYSQL_WRITE_ROWS_EVENT-- insert數(shù)據(jù)
3. MYSQL_UPDATE_ROWS_EVENT -- update數(shù)據(jù)
4. MYSQL_DELETE_ROWS_EVENT -- delete數(shù)據(jù)

當(dāng)一個(gè)事務(wù)提交后,MySQL 會(huì)把執(zhí)行的 SQL 處理成相應(yīng)的 binlog event,并持久化到 binlog 文件。

binlog 是 MySQL 對(duì)外輸出的重要途徑,只要你實(shí)現(xiàn) MySQL Replication Protocol,就可以流式的消費(fèi)MySQL 生產(chǎn)的 binlog event,具體協(xié)議見(jiàn) Replication Protocol。

由于歷史原因,協(xié)議繁瑣而詭異,這不是本文重點(diǎn)。

對(duì)于 ClickHouse 消費(fèi) MySQL binlog 來(lái)說(shuō),主要有以下3個(gè)難點(diǎn):

DDL 兼容

Delete/Update 支持

Query 過(guò)濾

DDL

DDL 兼容花費(fèi)了大量的代碼去實(shí)現(xiàn)。

首先,我們看看 MySQL 的表復(fù)制到 ClickHouse 后會(huì)變成什么樣子。

MySQL master:

mysql> show create table t1G;
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `a` int(11) NOT NULL,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

ClickHouse slave:

ATTACH TABLE t1
(
    `a` Int32,
    `b` Nullable(Int32),
    `_sign` Int8,
    `_version` UInt64
)
ENGINE = ReplacingMergeTree(_version)
PARTITION BY intDiv(a, 4294967)
ORDER BY tuple(a)
SETTINGS index_granularity = 8192

可以看到:

默認(rèn)增加了 2 個(gè)隱藏字段:_sign(-1刪除, 1寫入) 和 _version(數(shù)據(jù)版本)

引擎轉(zhuǎn)換成了 ReplacingMergeTree,以 _version 作為 column version

原主鍵字段 a 作為排序和分區(qū)鍵

這只是一個(gè)表的復(fù)制,其他還有非常多的DDL處理,比如增加列、索引等,感興趣可以觀摩 Parsers/MySQL 下代碼。

Update和Delete

當(dāng)我們?cè)?MySQL master 執(zhí)行:

mysql> delete from t1 where a=1;
mysql> update t1 set b=b+1;

ClickHouse t1數(shù)據(jù)(把 _sign 和 _version 一并查詢):

clickhouse :) select a,b,_sign, _version from t1;


SELECT
    a,
    b,
    _sign,
    _version
FROM t1


┌─a─┬─b─┬─_sign─┬─_version─┐
│ 1 │ 1 │     1 │        1 │
│ 2 │ 2 │     1 │        1 │
└───┴───┴───────┴──────────┘
┌─a─┬─b─┬─_sign─┬─_version─┐
│ 1 │ 1 │    -1 │        2 │
└───┴───┴───────┴──────────┘
┌─a─┬─b─┬─_sign─┬─_version─┐
│ 2 │ 3 │     1 │        3 │
└───┴───┴───────┴──────────┘

根據(jù)返回結(jié)果,可以看到是由 3 個(gè) part 組成。

part1 由mysql> insert into t1 values(1,1),(2,2)生成:

┌─a─┬─b─┬─_sign─┬─_version─┐
│ 1 │ 1 │     1 │        1 │
│ 2 │ 2 │     1 │        1 │
└───┴───┴───────┴──────────┘

part2 由mysql> delete from t1 where a=1生成:

┌─a─┬─b─┬─_sign─┬─_version─┐
│ 1 │ 1 │    -1 │        2 │
└───┴───┴───────┴──────────┘
說(shuō)明:
_sign = -1表明處于刪除狀態(tài)

part3 由update t1 set b=b+1生成:

┌─a─┬─b─┬─_sign─┬─_version─┐
│ 2 │ 3 │     1 │        3 │
└───┴───┴───────┴──────────┘

使用 final 查詢:

clickhouse :) select a,b,_sign,_version from t1 final;


SELECT
    a,
    b,
    _sign,
    _version
FROM t1
FINAL


┌─a─┬─b─┬─_sign─┬─_version─┐
│ 1 │ 1 │    -1 │        2 │
└───┴───┴───────┴──────────┘
┌─a─┬─b─┬─_sign─┬─_version─┐
│ 2 │ 3 │     1 │        3 │
└───┴───┴───────┴──────────┘


2 rows in set. Elapsed: 0.016 sec.

可以看到 ReplacingMergeTree 已經(jīng)根據(jù) _version 和 OrderBy 對(duì)記錄進(jìn)行去重。

Query

MySQL master:

mysql> select * from t1;
+---+------+
| a | b    |
+---+------+
| 2 |    3 |
+---+------+
1 row in set (0.00 sec)

ClickHouse slave:

clickhouse :) select * from t1;


SELECT *
FROM t1


┌─a─┬─b─┐
│ 2 │ 3 │
└───┴───┘


clickhouse :) select *,_sign,_version from t1;


SELECT
    *,
    _sign,
    _version
FROM t1


┌─a─┬─b─┬─_sign─┬─_version─┐
│ 1 │ 1 │    -1 │        2 │
│ 2 │ 3 │     1 │        3 │
└───┴───┴───────┴──────────┘
說(shuō)明:這里還有一條刪除記錄,_sign為-1

MaterializeMySQL 被定義成一種存儲(chǔ)引擎,所以在讀取的時(shí)候,會(huì)根據(jù) _sign 狀態(tài)進(jìn)行判斷,如果是-1則是已經(jīng)刪除,進(jìn)行過(guò)濾。

總結(jié)

ClickHouse 實(shí)時(shí)復(fù)制同步 MySQL 數(shù)據(jù)是 upstream 2020 的一個(gè) roadmap,在整體構(gòu)架上比較有挑戰(zhàn)一直無(wú)人接單,挑戰(zhàn)主要來(lái)自兩方面:

對(duì) MySQL 復(fù)制通道與協(xié)議非常熟悉

對(duì) ClickHouse 整體機(jī)制非常熟悉

這樣,在兩個(gè)本來(lái)有點(diǎn)遙遠(yuǎn)的山頭中間架起了一座高速,這條 10851號(hào)高速由 zhang1024(ClickHouse側(cè)) 和BohuTANG(MySQL復(fù)制) 兩個(gè)修路工聯(lián)合承建,目前正在接受 upstream 的驗(yàn)收。

關(guān)于同步 MySQL 的數(shù)據(jù),目前大家的方案基本都是在中間安置一個(gè) binlog 消費(fèi)工具,這個(gè)工具對(duì) event 進(jìn)行解析,然后再轉(zhuǎn)換成 ClickHouse 的 SQL 語(yǔ)句,寫到 ClickHouse server,鏈路較長(zhǎng),性能損耗較大。

10851號(hào)高速是在 ClickHouse 內(nèi)部實(shí)現(xiàn)一套 binlog 消費(fèi)方案,然后根據(jù) event 解析成ClickHouse 內(nèi)部的 block 結(jié)構(gòu),再直接寫回到底層存儲(chǔ)引擎,幾乎是最高效的一種實(shí)現(xiàn)方式。

基于 database 級(jí)的復(fù)制,實(shí)現(xiàn)了多源復(fù)制的功能,如果復(fù)制通道壞掉,我們只需在 ClickHouse 側(cè)刪除掉 database 然后再重建一次即可,非常方便。

對(duì)于單表的數(shù)據(jù)一致性,未來(lái)會(huì)實(shí)現(xiàn)一個(gè) MySQL CRC 函數(shù),用于校驗(yàn) MySQL 與 ClickHouse 的數(shù)據(jù)一致性。

要想富,先修路!

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)庫(kù)
    +關(guān)注

    關(guān)注

    7

    文章

    3712

    瀏覽量

    64025
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4671

    瀏覽量

    67769
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    789

    瀏覽量

    26283

原文標(biāo)題:從 MySQL 到 ClickHouse 實(shí)時(shí)復(fù)制與實(shí)現(xiàn)

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    MySQL的幾種復(fù)制配置

    MySQL主從復(fù)制、主主復(fù)制、雙主多配置
    發(fā)表于 04-16 09:50

    大數(shù)據(jù)實(shí)時(shí)分析領(lǐng)域的ClickHouse

    ClickHouse大數(shù)據(jù)實(shí)時(shí)分析領(lǐng)域的黑馬
    發(fā)表于 03-24 11:09

    mysql的主從復(fù)制

    mysql 主從復(fù)制
    發(fā)表于 04-28 14:30

    Centos7下如何搭建ClickHouse列式存儲(chǔ)數(shù)據(jù)庫(kù)

    性能的海量數(shù)據(jù)快速查詢的分布式實(shí)時(shí)處理平臺(tái),在數(shù)據(jù)匯總查詢方面(如GROUP BY),ClickHouse的查詢速度非???。2、數(shù)據(jù)庫(kù)特點(diǎn)(1)列式數(shù)據(jù)庫(kù)列式數(shù)據(jù)庫(kù)是以列相關(guān)存儲(chǔ)架構(gòu)進(jìn)行數(shù)據(jù)存儲(chǔ)的數(shù)據(jù)庫(kù)
    發(fā)表于 01-05 18:03

    MySQL實(shí)現(xiàn)延時(shí)復(fù)制

    公司有一套mysqlAB復(fù)制架構(gòu)的生產(chǎn)庫(kù),一主一的架構(gòu), 每周一凌晨0天都自動(dòng)做全備。
    的頭像 發(fā)表于 05-05 22:20 ?1458次閱讀
    <b class='flag-5'>MySQL</b><b class='flag-5'>實(shí)現(xiàn)</b>延時(shí)<b class='flag-5'>復(fù)制</b>

    利用MySQL進(jìn)行一主一的主從復(fù)制

    本文講述了如何使用MyBatisPlus+ShardingSphereJDBC進(jìn)行讀寫分離,以及利用MySQL進(jìn)行一主一的主從復(fù)制。
    的頭像 發(fā)表于 07-28 09:47 ?944次閱讀

    MySQL 5.7并行復(fù)制實(shí)現(xiàn)原理與調(diào)優(yōu)

    眾所周知,MySQL復(fù)制延遲是一直被詬病的問(wèn)題之一,然而在Inside君之前的兩篇博客中(1,2)中都已經(jīng)提到了MySQL 5.7版本已經(jīng)支持“真正”的并行復(fù)制功能,官方稱為為enh
    的頭像 發(fā)表于 12-23 14:52 ?453次閱讀

    MySQL 5.6并行復(fù)制架構(gòu)及并行復(fù)制原理

    ySQL 5.6版本也支持所謂的并行復(fù)制,但是其并行只是基于schema的,也就是基于庫(kù)的。如果用戶的MySQL數(shù)據(jù)庫(kù)實(shí)例中存在多個(gè)schema,對(duì)于機(jī)復(fù)制的速度的確可以有比較大的幫
    發(fā)表于 12-23 14:52 ?468次閱讀

    探討MySQL復(fù)制機(jī)制實(shí)現(xiàn)的方式

    MySQL Replication(主從復(fù)制)是指數(shù)據(jù)變化可以從一個(gè)MySQL Server被復(fù)制到另一個(gè)或多個(gè)MySQL Server上,
    的頭像 發(fā)表于 04-12 09:29 ?571次閱讀

    mysql主從復(fù)制三種模式

    MySQL主從復(fù)制是一種常見(jiàn)的數(shù)據(jù)同步方式,它可以實(shí)現(xiàn)將一個(gè)數(shù)據(jù)庫(kù)的更改同步其他多個(gè)數(shù)據(jù)庫(kù)的功能。主從復(fù)制可以提高數(shù)據(jù)庫(kù)的可用性和性能,以
    的頭像 發(fā)表于 11-16 14:04 ?1169次閱讀

    mysql如何實(shí)現(xiàn)主從復(fù)制的具體流程

    主從復(fù)制MySQL數(shù)據(jù)庫(kù)中常用的數(shù)據(jù)復(fù)制技術(shù)之一,它的主要目的是將一個(gè)數(shù)據(jù)庫(kù)服務(wù)器上的數(shù)據(jù)復(fù)制到其他服務(wù)器上,以實(shí)現(xiàn)數(shù)據(jù)的備份、高可用和分
    的頭像 發(fā)表于 11-16 14:10 ?591次閱讀

    mysql主從復(fù)制主要有幾種模式

    MySQL主從復(fù)制MySQL數(shù)據(jù)庫(kù)中常用的一種數(shù)據(jù)復(fù)制方式,用于實(shí)現(xiàn)數(shù)據(jù)的備份、負(fù)載均衡、故障恢復(fù)等目的。主從
    的頭像 發(fā)表于 11-16 14:15 ?1036次閱讀

    mysql主從復(fù)制的原理

    MySQL主從復(fù)制是一種數(shù)據(jù)庫(kù)復(fù)制技術(shù),它允許將一個(gè)MySQL數(shù)據(jù)庫(kù)的更新操作自動(dòng)復(fù)制到其他MySQL
    的頭像 發(fā)表于 11-16 14:18 ?404次閱讀

    mysql主從復(fù)制 混合類型的復(fù)制

    MySQL主從復(fù)制是一種常用的數(shù)據(jù)復(fù)制技術(shù),可以實(shí)現(xiàn)數(shù)據(jù)從一個(gè)MySQL服務(wù)器(主服務(wù)器)復(fù)制到
    的頭像 發(fā)表于 11-16 14:20 ?447次閱讀

    mysql主從復(fù)制數(shù)據(jù)不一致怎么辦

    MySQL主從復(fù)制是一種常用的數(shù)據(jù)復(fù)制技術(shù),用于實(shí)現(xiàn)數(shù)據(jù)的實(shí)時(shí)同步和分布式部署。然而,在實(shí)際應(yīng)用中,主從
    的頭像 發(fā)表于 11-16 14:35 ?1887次閱讀