Replicación en tiempo real de MySQL a Clickhouse


MySQL y Clickhouse son dos bases de datos completamente diferentes, las cuales tienen sus propias ventajas y desventajas, y los escenarios comerciales para los que son adecuadas también son diferentes. En los negocios reales, debemos elegir la más adecuada de acuerdo con las características y ventajas de la base de datos en sí Escena empresarial. Aunque la base de datos MySQL tradicional soporta muy bien los negocios OLTP, todavía existen ciertos cuellos de botella de rendimiento en escenarios comerciales como OLAP que requieren análisis estadístico de grandes cantidades de datos. Si queremos hacer un mejor análisis estadístico de BI y consultar los datos centrales del negocio en línea, debemos enfrentarnos a cómo sincronizar los datos en línea con la base de datos de análisis estadístico correspondiente. A partir de 2020, Clickhouse ha lanzado el motor MaterializeMySQL, que realiza el uso de Clickhouse como una base de datos esclava de MySQL, sincronización en tiempo real de datos MySQL y un salto de OLTP a OLAP.

一 、 MaterialiseMySQL

1.1 Comparación simple entre MySQL y CK

Las principales similitudes y diferencias entre MySQL y Clickhouse son las siguientes:

MySQL Clickhouse
Base de datos relacional, elementos de apoyo Base de datos de columna distribuida, no admite transacciones
Modo de almacenamiento de filas, adecuado para leer la menor cantidad posible de datos de filas El modo de almacenamiento de columna y la alta tasa de compresión de datos tienen una ventaja natural para la lectura masiva de datos.
Servicio multiproceso de un solo proceso, una sola consulta de solicitud comercial no puede utilizar de manera efectiva múltiples recursos de CPU Paralelo de varios núcleos
Para negocios OLTP Negocio OLAP orientado al procesamiento analítico en línea

1.2 Principio MaterializeMySQL

En la segunda mitad de 2020, Yandex Company lanzó el motor MaterializeMySQL en la comunidad ClickHouse, que se utiliza principalmente para admitir la sincronización de datos completa e incremental en tiempo real desde MySQL. Actualmente es compatible con la versión MySQL 5.6 / 5.7 / 8.0, compatible con declaraciones Delete / Update y las operaciones DDL más utilizadas.

Como todos sabemos, la propia replicación de MySQL se basa principalmente en el registro de transacciones binlog, y el motor MaterializeMySQL no es una excepción. Sin embargo, la diferencia entre la replicación binlog de MySQL nativo es que debido a las diferencias gramaticales entre los dos, MaterializeMySQL no convierte las declaraciones SQL en el evento en declaraciones específicas en el CK para su ejecución, sino que convierte directamente el evento Binlog en el subyacente. Estructura de bloque: luego se escribe directamente en el motor de almacenamiento subyacente, que está cerca de la replicación física.

Proceso de implementación de MaterializeMySQL:

  • MaterializeMySQL admite la replicación a nivel de base de datos.
  • Después de crear una copia a nivel de base de datos en Clickhouse, clickhouse se conecta a los datos a través de TCP / IP a través de nuestra cuenta de base de datos designada, ejecuta la tabla Flush con bloqueo de lectura en la base de datos y obtiene información de metadatos de estructura de tabla y binlog relacionados; después de que se copian los metadatos Libere el bloqueo global de solo lectura y comience a copiar la información de datos de la tabla a través de select * from table_name.
  • Para la posterior sincronización incremental de datos, MaterializeMySQL realiza la sincronización en tiempo real mediante el análisis del evento binlog (MYSQL_QUERY_EVENT (DDL), MYSQL_WRITE_ROWS_EVENT (insertar), MYSQL_UPDATE_ROWS_EVENT (actualizar), MYSQL_DELETE_ROWS_ROWS_
  • Para las operaciones DDL, MaterializeMySQL usa la clave principal de los datos de la tabla MySQL como clave de clasificación y clave de partición de la tabla CK de forma predeterminada, pero debido a la diferencia entre las definiciones de datos de Clickhouse y MySQL, la declaración DDL también se convertirá en consecuencia.
  • Para las operaciones de actualización / eliminación, MaterializeMySQL introduce el campo oculto de _version, que se utiliza para el control de versiones, y combina el campo _sign para marcar la validez de los datos.

Cuando MaterializeMySQL crea un canal de replicación, durante la fase de sincronización de inicialización completa, puede ver los detalles de ejecución específicos de MySQL a través de general_log. Los registros de ejecución específicos son los siguientes:

2021-03-14T15:40:02.016351+08:00	   26 Connect	[email protected] on ck_test using TCP/IP
2021-03-14T15:40:02.017402+08:00	   26 Query	SET NAMES utf8
2021-03-14T15:40:02.018822+08:00	   26 Query	SHOW VARIABLES WHERE (Variable_name = 'log_bin' AND upper(Value) = 'ON') OR (Variable_name = 'binlog_format' AND upper(Value) = 'ROW') OR (Variable_name = 'binlog_row_image' AND upper(Value) = 'FULL') OR (Variable_name = 'default_authentication_plugin' AND upper(Value) = 'MYSQL_NATIVE_PASSWORD')
2021-03-14T15:40:02.032549+08:00	   26 Query	SELECT version() AS version
2021-03-14T15:40:02.033620+08:00	   26 Query	FLUSH TABLES
2021-03-14T15:40:02.051444+08:00	   26 Query	FLUSH TABLES WITH READ LOCK
2021-03-14T15:40:02.052364+08:00	   26 Query	SHOW MASTER STATUS
2021-03-14T15:40:02.053295+08:00	   26 Query	SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
2021-03-14T15:40:02.054027+08:00	   26 Query	START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */
2021-03-14T15:40:02.055520+08:00	   26 Query	SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES  WHERE TABLE_SCHEMA = 'ck_test'
2021-03-14T15:40:02.057527+08:00	   26 Query	SHOW CREATE TABLE ck_test.t1
2021-03-14T15:40:02.060780+08:00	   26 Query	SHOW CREATE TABLE ck_test.t2
2021-03-14T15:40:02.062275+08:00	   26 Query	UNLOCK TABLES
2021-03-14T15:40:02.075348+08:00	   26 Query	SELECT * FROM ck_test.t2
2021-03-14T15:40:02.101797+08:00	   26 Query	SELECT * FROM ck_test.t1
2021-03-14T15:40:02.106329+08:00	   26 Query	COMMIT
2021-03-14T15:40:02.109026+08:00	   27 Connect	[email protected] on  using TCP/IP
2021-03-14T15:40:02.109637+08:00	   27 Query	SET @master_binlog_checksum = 'CRC32'
2021-03-14T15:40:02.110123+08:00	   27 Query	SET @master_heartbeat_period = 1000000000
2021-03-14T15:40:02.111290+08:00	   27 Binlog Dump GTID	Log: '' Pos: 4 GTIDs: '4a2dfc1c-1f50-11eb-a38b-fa057042bc00:1-53,
a4ec8037-1a70-11eb-91ff-fa9f1ef63700:1-1741042'

2. Replicación en tiempo real de MySQL-> CK

1.1 Preparación ambiental

1 、 MySQL

  • Habilite el registro de binlog y row_format = row
  • Copiar usando el modo gtid
gtid_mode=ON
enforce_gtid_consistency=1
binlog_format=ROW

2 、 Clickhouse

1) Parámetros ambientales

-- 该参数默认关闭,若需要使用MaterializeMySQL引擎,必须打开该参数
mdw :) set allow_experimental_database_materialize_mysql=1;             

2) Cree un canal de replicación

-- 语法
CREATE DATABASE ${dbname} ENGINE = MaterializeMySQL('${mysql_ip}:${mysql_port}', '${mysql_dbname}', '${mysql_user}', '${mysql_passoword}');

-- 执行SQL
mdw :) CREATE DATABASE ck_test ENGINE = MaterializeMySQL('172.16.104.13:3306', 'ck_test', 'root', '123');

3) Copiar información

Para la información de replicación en tiempo real de MySQL, se almacena en el directorio de metadatos en datadir.

-- MySQL的binlog位点信息
root@mysql 15:05:  [ck_test]> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.000005
         Position: 4048
     Binlog_Do_DB:
 Binlog_Ignore_DB:
Executed_Gtid_Set: 4a2dfc1c-1f50-11eb-a38b-fa057042bc00:1-37,
a4ec8037-1a70-11eb-91ff-fa9f1ef63700:1-1741042
1 row in set (0.00 sec)

-- Clickhouse复制位点信息
[root@mdw ck_test]# pwd
/data/clickhouse-server/data/metadata/ck_test
[root@mdw ck_test]# cat .metadata
Version:	2
Binlog File:	mysql-bin.000005                                            //binlog文件
Executed GTID:	4a2dfc1c-1f50-11eb-a38b-fa057042bc00:1-37,a4ec8037-1a70-11eb-91ff-fa9f1ef63700:1-1741042        //GTID信息
Binlog Position:	4048                                                    //binlog位点
Data Version:	9                                                           //数据版本信息,全局递增

1.2 Prueba de funcionamiento básico

1. Sincronización de la escritura de datos

Para todos los datos de MySQL, habrá campos ocultos _sign y _version correspondientes en CK, que se utilizan para marcar y consultar el control de versiones. ,

-- MySQL
root@mysql 14:44:  [ck_test]> create table t2(id int primary key not null auto_increment,name varchar(2));
Query OK, 0 rows affected (0.03 sec)

root@mysql 14:45:  [ck_test]> insert into t2 values(null,'aa'),(null,'bb');
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

root@mysql 14:45:  [ck_test]> select * from t2;
+----+------+
| id | name |
+----+------+
|  1 | aa   |
|  2 | bb   |
+----+------+
2 rows in set (0.01 sec)

-- Clickhouse
mdw :) select * from ck_test.t2 order by id ;

SELECT *
FROM ck_test.t2
ORDER BY id ASC

┌─id─┬─name─┐
│  1 │ aa   │
└────┴──────┘
┌─id─┬─name─┐
│  2 │ bb   │
└────┴──────┘

2 rows in set. Elapsed: 0.009 sec.

-- Clickhouse隐藏字段查询
mdw :) select *,_sign,_version from ck_test.t2 order by id;

SELECT
    *,
    _sign,
    _version
FROM ck_test.t2
ORDER BY id ASC

┌─id─┬─name─┬─_sign─┬─_version─┐
│  1 │ aa   │     1 │        7 │                //一次性写入的_version=7一致,由于是insert操作,_sign=1。
│  2 │ bb   │     1 │        7 │
└────┴──────┴───────┴──────────┘

2 rows in set. Elapsed: 0.003 sec.


2. Actualización de datos

Para la operación de actualización de MySQL, cuando consultamos directamente los datos de la tabla CK, podemos ver que los datos de la tabla se han "actualizado" normalmente, pero cuando consultamos adicionalmente la información de _sign, _version, podemos encontrar que los datos no se eliminan físicamente. antes de la actualización. Por lo tanto, para la operación de actualización de Clickhouse, el registro modificado en realidad se escribe y se marca como _sign = 1, _version = $ {current version} +1. Cuando ejecutemos la consulta, CK nos ayudará finalmente a regresar como información normal del conjunto de resultados.

-- MySQL
root@mysql 14:45:  [ck_test]> select * from t2;
+----+------+
| id | name |
+----+------+
|  1 | aa   |
|  2 | bb   |
+----+------+
2 rows in set (0.01 sec)

root@mysql 14:47:  [ck_test]> update t2 set name='aaa' where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

root@mysql 14:47:  [ck_test]> select * from t2;
+----+------+
| id | name |
+----+------+
|  1 | aaa  |
|  2 | bb   |
+----+------+
2 rows in set (0.01 sec)

-- Clickhouse
mdw :) select * from ck_test.t2 order by id ;                   //可以看到,正常的查询,CK已经帮我们做了处理

SELECT *
FROM ck_test.t2
ORDER BY id ASC

┌─id─┬─name─┐
│  1 │ aaa  │
└────┴──────┘
┌─id─┬─name─┐
│  2 │ bb   │
└────┴──────┘

2 rows in set. Elapsed: 0.014 sec.

mdw :) select *,_sign,_version from ck_test.t2 order by id;

SELECT
    *,
    _sign,
    _version
FROM ck_test.t2
ORDER BY id ASC

┌─id─┬─name─┬─_sign─┬─_version─┐
│  1 │ aaa  │     1 │        8 │                                //update更新后的数据被写入ck表,_version+1
└────┴──────┴───────┴──────────┘
┌─id─┬─name─┬─_sign─┬─_version─┐
│  1 │ aa   │     1 │        7 │
│  2 │ bb   │     1 │        7 │
└────┴──────┴───────┴──────────┘

3 rows in set. Elapsed: 0.008 sec.

3. Eliminación de datos

Para la operación Eliminar, cuando consultamos directamente los datos de la tabla CK, podemos ver que los datos de la tabla se han "eliminado" normalmente, pero cuando consultamos adicionalmente la información de _sign, _version, podemos encontrar que los datos no se eliminan físicamente antes. la actualización, y es agregar una nueva fila de datos de registro de fila que deben eliminarse, y marcar _sign = -1, _version = versión actual +1, por lo que para la operación de eliminación de ck, el registro no se eliminará físicamente directamente, pero se eliminará mediante una marca de signo. Cuando ejecutamos la consulta de consulta, CK nos ayuda finalmente a volver a la información normal del conjunto de resultados de acuerdo con el control de versiones.

-- MySQL
root@mysql 14:47:  [ck_test]> select * from t2;
+----+------+
| id | name |
+----+------+
|  1 | aaa  |
|  2 | bb   |
+----+------+
2 rows in set (0.00 sec)

root@mysql 14:48:  [ck_test]> delete from t2 where id=2;
Query OK, 1 row affected (0.01 sec)

root@mysql 14:48:  [ck_test]> select * from t2;
+----+------+
| id | name |
+----+------+
|  1 | aaa  |
+----+------+
1 row in set (0.01 sec)

-- Clickhouse
mdw :) select * from ck_test.t2 order by id ;                           //query操作正常显示结果集信息

SELECT *
FROM ck_test.t2
ORDER BY id ASC

┌─id─┬─name─┐
│  1 │ aaa  │
└────┴──────┘

1 rows in set. Elapsed: 0.009 sec.

mdw :) select *,_sign,_version from ck_test.t2 order by id;

SELECT
    *,
    _sign,
    _version
FROM ck_test.t2
ORDER BY id ASC

┌─id─┬─name─┬─_sign─┬─_version─┐
│  1 │ aaa  │     1 │        8 │
└────┴──────┴───────┴──────────┘
┌─id─┬─name─┬─_sign─┬─_version─┐
│  1 │ aa   │     1 │        7 │
│  2 │ bb   │    -1 │        9 │                                            //新增删除记录行,并标记_sign=-1表示删除操作
│  2 │ bb   │     1 │        7 │
└────┴──────┴───────┴──────────┘

4 rows in set. Elapsed: 0.008 sec.


4 、 DDL

1) Para la información de la estructura de datos de la tabla CK, dado que MaterializeMySQL no es compatible con la sintaxis show create xx por el momento, podemos ver la información de la estructura de la tabla creada por CK a través del archivo físico correspondiente.

[root@mdw metadata]# cat ck_test
cat: ck_test: 是一个目录
[root@mdw metadata]# cat ck_test.sql
ATTACH DATABASE ck_test
ENGINE = MaterializeMySQL('172.16.104.13:3306', 'ck_test', 'root', '123')
[root@mdw metadata]# cat ck_test/t2.sql
ATTACH TABLE t2
(
    `id` Int32,
    `name` Nullable(String),
    `_sign` Int8 MATERIALIZED 1,
    `_version` UInt64 MATERIALIZED 1
)
ENGINE = ReplacingMergeTree(_version)
PARTITION BY intDiv(id, 4294967)                                    //分区键、排序键均由MySQL表数据主键继承
ORDER BY tuple(id)
SETTINGS index_granularity = 8192

2) Nueva operación de campo DDL

-- MySQL新增表字段
root@mysql 14:48:  [ck_test]> alter table t2 add age int;
Query OK, 0 rows affected (0.07 sec)
Records: 0  Duplicates: 0  Warnings: 0

root@mysql 14:52:  [ck_test]> select * from t2;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | aaa  | NULL |
+----+------+------+
1 row in set (0.00 sec)


-- Clickhouse表字段信息
[root@mdw metadata]# cat ck_test/t2.sql
ATTACH TABLE t2
(
    `id` Int32,
    `name` Nullable(String),
    `age` Nullable(Int32),                                          //CK表同步MySQL新增字段,对于ck这种列存储来讲,新增字段的操作还是比较简单的
    `_sign` Int8 MATERIALIZED 1,
    `_version` UInt64 MATERIALIZED 1
)
ENGINE = ReplacingMergeTree(_version)
PARTITION BY intDiv(id, 4294967)
ORDER BY tuple(id)

mdw :) select * from ck_test.t2 order by id ;

SELECT *
FROM ck_test.t2
ORDER BY id ASC

┌─id─┬─name─┬──age─┐
│  1 │ aaa  │ ᴺᵁᴸᴸ │
└────┴──────┴──────┘

1 rows in set. Elapsed: 0.010 sec.

mdw :) select *,_sign,_version from ck_test.t2 order by id;

SELECT
    *,
    _sign,
    _version
FROM ck_test.t2
ORDER BY id ASC

┌─id─┬─name─┬──age─┬─_sign─┬─_version─┐
│  1 │ aa   │ ᴺᵁᴸᴸ │     1 │        7 │
│  1 │ aaa  │ ᴺᵁᴸᴸ │     1 │        8 │
│  2 │ bb   │ ᴺᵁᴸᴸ │    -1 │        9 │
│  2 │ bb   │ ᴺᵁᴸᴸ │     1 │        7 │
└────┴──────┴──────┴───────┴──────────┘

4 rows in set. Elapsed: 0.023 sec.

3. Preguntas y pensamientos de seguimiento

  • Para que Clickhouse cree una replicación, es necesario obtener un bloqueo de lectura global y realizar una consulta de exploración de tabla completa de la tabla de crecimiento, que son algunas operaciones que consumen muchos recursos. Por lo tanto, todavía se recomienda copiar de la biblioteca con binlog y log_slave_updates como fuente para la replicación de ck.
  • Cuando ck crea un canal de replicación, los permisos mínimos de usuario de la base de datos requeridos son: SELECT, REPLICATION SLAVE ON .
  • Para el negocio OLTP normal, los cambios de datos de nuestra tabla todavía tienen operaciones de actualización frecuentes, y todos realizan una operación de inserción redundante. El primer punto que nos preocupa es el rendimiento. ¿Las actualizaciones frecuentes de datos harán que ck consuma una gran cantidad de recursos y el segundo punto es el consumo de espacio en disco? ¿Ck eliminará rápidamente los datos históricos no válidos en algunas operaciones de fusión en segundo plano?

Referencia del artículo:

La autopista de MySQL a ClickHouse-MaterializeMySQL engine :
ClickHouse y sus amigos (9) Implementación y replicación en tiempo real de MySQL
Documento oficial de CK
Clickhouse para Github

Supongo que te gusta

Origin blog.csdn.net/weixin_37692493/article/details/114791399
Recomendado
Clasificación