企业里随着数据量的增加,以及日趋复杂的分析性业务需求,主要适用于OLTP场景的MySQL压力越来越大。多年前还能免费试用的infobright社区版也早就销声匿迹,infinidb被MariaDB收入囊中之后改头换面变成ColumnStore,但最近几年发展的平平淡淡,都不是理想的OLAP方案。
战斗民族出品的ClickHouse这几年则是风头正劲,国内用户也越来越多,几大公有云上也提供相应的产品服务,是目前市面上最快的OLAP数据库,性能远超Vertica、Sybase IQ等。关于ClickHouse的性能也可以关注我以前的一份测试报告:ClickHouse性能测试。
ClickHouse对MySQL的兼容性也很好,除了很多语法相同或接近外,甚至还可以利用MySQL客户端(协议)连接到ClickHouse。
ClickHouse 可以挂载为 MySQL 的一个从库 ,先全量再增量的实时同步 MySQL 数据,这个功能可以说是今年最亮眼、最刚需的功能,基于它我们可以轻松的打造一套企业级解决方案,让 OLTP 和 OLAP 的融合从此不再头疼。目前支持 MySQL 5.6/5.7/8.0 版本,兼容 Delete/Update 语句,及大部分常用的 DDL 操作。只需要安装最新版本的ClickHouse就可以体验到这个新特性了,不过该特性还处于experimental阶段,还在不断完善中。
ProxySQL是一款强大的中间件为MySQL的架构提供了有力的支持,支持传统主从复制、半同步复制、MGR、PXC等多种MySQL架构,还支持故障自动检测和切换、连接池、读写分离、日志记录、监控、集群部署等多项实用功能。当然了,ProxySQL最大的缺点是性能损失较大,预计至少有20% ~ 30%的性能损失,因此如果是在高性能场景下可能不太合适。不过可以考虑通过分库分表等方式降低单节点压力,充分发挥ProxySQL的集群功能。
ClickHouse和ProxySQL的安装本文不再赘述,直接开始动手构建HTAP系统。下面是整体架构示意图
登入ClickHouse后,执行下面的命令启用新特性:
clickhouse :) SET allow_experimental_database_materialize_mysql = 1;
在ClickHouse中,创建一个复制通道,即可构建一个MySQL复制从库,例如:
clickhouse :) CREATE DATABASE test ENGINE = MaterializeMySQL('172.24.10.10:3306', 'test', 'repl', 'repl'); clickhouse :) use test; clickhouse :) show tables; ┌─name─────┐ │ sbtest1 │ │ sbtest10 │ │ sbtest11 │ ... 32 rows in set. Elapsed: 0.006 sec.
首次创建复制通道后,ClickHouse会快速从MySQL主库读取所有数据并应用,可以查看数据复制的进度:
[root@yejr.run]# cat metadata/sbtest/.metadata Version: 2 Binlog File: binlog.001496 Executed GTID: 097ee9f2-2ded-11eb-9211-e4434ba52b50:1-952676723 Binlog Position: 789663343 Data Version: 2
提醒:在这里,我设置的是主从复制专用账号。相对于普通的主从复制账号,用于ClickHouse从库的账号至少还要加上只读权限,例如:
[root@yejr.run]> show grants for repl; +--------------------------------------------------------------------------+ | Grants for repl@% | +--------------------------------------------------------------------------+ | GRANT RELOAD, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO `repl`@`%` | | GRANT SELECT ON `test`.* TO `repl`@`%` | +--------------------------------------------------------------------------+
ClickHouse的MaterializeMySQL引擎从MySQL复制数据的速度非常之快,甚至比MySQL原生的从库还要更快,大家可以亲身感受体验下。
接下来,再在ClickHouse中创建一个业务账号,以及一个服务监控账号(用于ProxySQL对后端服务的监控)。编辑ClickHouse的配置文件 users.xml,增加两个用户:
<app_user> <password>app_user</password> <networks incl="networks" replace="replace"> <ip>::/0</ip> </networks> <profile>default</profile> <quota>default</quota> </app_user> <monitor> <password>monitor</password> <networks incl="networks" replace="replace"> <ip>::/0</ip> </networks> <profile>default</profile> <quota>default</quota> </monitor>
我只设置了简单密码,也没有修改其权限和quota模式,仅演示用,线上生产环境请自行调整以合规。
配置mysql_servers表,增加两条记录,并使配置生效:
proxysql> insert into mysql_servers(hostgroup_id, hostname, port) values('0', '172.24.10.10', '3306'); proxysql> insert into mysql_servers(hostgroup_id, hostname, port) values('1', '172.24.10.11', '9004'); proxysql> save mysql servers to disk; load mysql servers to run;
其中,172.24.10.10:3306 是MySQL主库,172.24.10.11:9004是ClickHouse从库,9004端口是ClickHouse里给MySQL客户端连接专用的,可以用MySQL客户端(协议)连接进来执行各种操作。
hostgroup分别为0和1,0用于读写组,1用于只读组。
配置mysql_users表,加入业务账号和监控账号:
proxysql> select username,password,active from mysql_users; +-----------+----------+--------+ | username | password | active | +-----------+----------+--------+ | app_user | app_user | 1 | | monitor | monitor | 1 | +-----------+----------+--------+ proxysql> save mysql users to disk; load mysql users to runtime;
配置mysql_query_rules表,这个是关键,用于判断将哪些SQL转发到MySQL主库,哪些转发到ClickHouse:
proxysql> select rule_id, active, match_pattern,destination_hostgroup from mysql_query_rules; +---------+--------+-------------------------+-----------------------+ | rule_id | active | match_pattern | destination_hostgroup | +---------+--------+-------------------------+-----------------------+ | 1 | 1 | ^SELECT.*\+CLICKHOUSE.* | 1 | +---------+--------+-------------------------+-----------------------+ proxysql> save mysql query rules to disk; load mysql query rules to run;
上述规则的意思是,当SELECT语句中包含 "+CLICKHOUSE" 关键字时,就会自动转发到 ClickHouse 后端去处理,其余的都发送到MySQL后端处理。例如下面这两条SQL就会分别转发到MySQL和ClickHouse后端:
#SQL #1 [root@yejr.run]> SELECT * FROM sbtest1 WHERE id=1; #SQL #2 [root@yejr.run]> SELECT /*+CLICKHOUSE*/ * FROM sbtest1 WHERE id=1;