ClickHouse从入门到精通(四)
ClickHouse 高级篇
数据一致性【重点】
- 查询 CK 手册发现,即便对数据一致性支持最好的 Mergetree,也只是保证最终一致性。
- 我们在使用 ReplacingMergeTree、SummingMergeTree 这类表引擎的时候,会出现短暂数据不一致的情况。
- 在某些对一致性非常敏感的场景,通常有以下几种解决方案。
0. 准备测试数据
-- 创建表
create table t_v1(
user_id UInt64,
score String,
deleted UInt8 DEFAULT 0,
create_time DateTime DEFAULT toDateTime(0)
) engine = ReplacingMergeTree(create_time)
order by user_id;
-- user_id: 数据去重更新的标识
-- create_time: 版本号字段,每组数据中 create_time最大的一行表示最新的数据
-- deleted: 自定义的一个标志位,0 未删除,1 删除
-- 写入 1000万 测试数据
insert into table t_v1(user_id, score)
with (select ['A', 'B', 'C', 'D', 'E', 'F', 'G']) as dict
select number as user_id, dict[number % 7 + 1] from numbers(10000000);
-- 修改前 50 万 行数据,修改内容包括 name 字段和 create_time 版本号字段
insert into table t_v1(user_id, score, create_time)
with (select ['AA', 'BB', 'CC', 'DD', 'EE', 'FF', 'GG']) as dict
select number as user_id, dict[number % 7 + 1], now() as create_time from numbers(500000);
-- 统计总数
select count() from t_v1;
┌──count()─┐
│ 10500000 │
└──────────┘
1. 手动 OPTIMIZE
- 在写入数据后,立刻执行 OPTIMIZE 强制触发新写入分区的合并动作。【不推荐】
- 语法:https://clickhouse.com/docs/en/sql-reference/statements/optimize
OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
optimize table t_v1 final;
-- 再次查询总数
select count() from t_v1;
┌──count()─┐
│ 10000000 │
└──────────┘
2. 通过 group by 去重
- 执行去重查询
select user_id,
argMax(score, create_time) as score,
argMax(deleted, create_time) as deleted,
max(create_time) as ctime from t_v1
group by user_id
having deleted = 0;
-- argMax(field1, field2): 按照 field2 的最大值取 field 的值
- 当我们更新数据时,会写入一行新的数据,例如上面语句中,通过查询最大的create_time 得到修改后的 score 字段值。
-- 创建视图
create view v_t_v1 as
select user_id,
argMax(score, create_time) as score,
argMax(deleted, create_time) as deleted,
max(create_time) as ctime from t_v1
group by user_id
having deleted = 0;
- 插入重复数据,再次查询
-- 再次插入一条数据
insert into table t_v1(user_id, score, create_time) values(0, 'AAAA', now());
-- 再次查询
select * from v_t_v1 where user_id = 0;
┌─user_id─┬─score─┬─deleted─┬───────────────ctime─┐
│ 0 │ AAAA │ 0 │ 2022-04-26 22:53:22 │
└─────────┴───────┴─────────┴─────────────────────┘
-- 再次插入一条标记为删除的数据
insert into table t_v1(user_id, score, deleted, create_time) values(0, 'AAAA', 1, now());
-- 再次查询,刚才那条数据看不到了
select * from v_t_v1 where user_id = 0;
0 rows in set.
- 这行数据并没有被真正的删除,而是被过滤掉了。在一些合适的场景下,可以结合表级别的 TTL 最终将物理数据删除。
3. 通过 FINAL 查询
- 在查询语句后增加 FINAL 修饰符,这样在查询的过程中将会执行 Merge 的特殊逻辑(例如数据去重,预聚合等)。
- 但是这种方法在早期版本基本没有人使用,因为在增加 FINAL 之后,我们的查询将会变成一个单线程的执行过程,查询速度非常慢。
- 在v20.5.2.7-stable版本中,FINAL 查询支持多线程执行,并可以通过max_final_threads参数控制单个查询的线程数。但是目前读取 part 部分的动作依然是串行的。
- FINAL 查询最终的性能和很多因素相关,列字段的大小、分区的数量等等都会影响到最终的查询时间,所以还要结合实际场景取舍。
- 参考连接:https://github.com/ClickHouse/ClickHouse/pull/10463
-- ① 普通语句查询
select * from datasets.visits_v1 where StartDate = '2014-03-17' limit 100 settings max_threads = 2;
-- 查看执行计划
explain pipeline select * from datasets.visits_v1 where StartDate = '2014-03-17' limit 100 settings max_threads = 2;
┌─explain─────────────────────────┐
│ (Expression) │
│ ExpressionTransform × 2 │
│ (SettingQuotaAndLimits) │
│ (Limit) │
│ Limit 2 → 2 │
│ (ReadFromMergeTree) │
│ MergeTreeThread × 2 0 → 1 │
└─────────────────────────────────┘ -- 明显将由 2 个线程并行读取 part 查询。
-- ② FINAL 查询
select * from datasets.visits_v1 final where StartDate = '2014-03-17' limit 100 settings max_threads = 2;
- 可以明细看到查询速度没有普通的查询快,但是相比之前老版本已经有了一些提升,查看 FINAL 查询的执行计划
explain pipeline select * from datasets.visits_v1 final where StartDate = '2014-03-17' limit 100 settings max_threads = 2;
┌─explain──────────────────────────────────┐
│ (Expression) │
│ ExpressionTransform × 2 │
│ (Limit) │
│ Limit 2 → 2 │
│ (Filter) │
│ FilterTransform × 2 │
│ (SettingQuotaAndLimits) │
│ (ReadFromMergeTree) │
│ ExpressionTransform × 2 │
│ CollapsingSortedTransform × 2 │
│ Copy 1 → 2 │
│ AddingSelector │
│ ExpressionTransform │
│ MergeTreeInOrder 0 → 1 │
└──────────────────────────────────────────┘
- 从 CollapsingSortedTransform 这一步开始已经是多线程执行,但是读取 part 部分的动作还是串行。
数据一致性总结:ReplacingMergeTree 不能保证查询时没重复,只能保证最终一致性
解决方案:
1、手动执行 optimize:生产环境不推荐
2、通过 sql 实现去重:group by ==>> 高级玩法:加标记字段
3、使用final:
20.5 之前版本,final是单线程;
20.5 之后版本,final可以是多线程,但读取是串行
4、重复一点无所谓:100万日活,统计出来100万零1千
物化视图
- ClickHouse 的物化视图是一种查询结果的持久化,它确实是给我们带来了查询效率的提升。用户查起来跟表没有区别,它就是一张表,它也像是一张时刻在预计算的表,创建的过程它是用了一个特殊引擎,加上后来 as select,就是 create 一个 table as select 的写法。
- “查询结果集”的范围很宽泛,可以是基础表中部分数据的一份简单拷贝,也可以是多表 join 之后产生的结果或其子集,或者原始数据的聚合指标等等。所以,物化视图不会随着基础表的变化而变化,所以它也称为快照(snapshot) 。
- 参考文档:https://clickhouse.com/docs/en/sql-reference/statements/create/view#materialized
1. 概述
物化视图与普通视图的区别
- 普通视图不保存数据,保存的仅仅是查询语句,查询的时候还是从原表读取数据,可以将普通视图理解为是个子查询。物化视图则是把查询的结果根据相应的引擎存入到了磁盘或内存中,对数据重新进行了组织,你可以理解物化视图是完全的一张新表。
优缺点
- 优点:查询速度快,要是把物化视图这些规则全部写好,它比原数据查询快了很多,总的行数少了,因为都预计算好了。
- 缺点:它的本质是一个流式数据的使用场景,是累加式的技术,所以要用历史数据做去重、聚合这样的分析,在物化视图里面是不太好用的。在某些场景的使用也是有限的。而且如果一张表加了好多物化视图,在写这张表的时候,就会消耗很多机器的资源,比如数据带宽占满、存储一下子增加了很多。
基本语法
- 也是 create 语法,会创建一个隐藏的目标表来保存视图数据。也可以 TO 表名,保存到一张显式的表。没有加 TO 表名,表名默认就是
.inner.物化视图名
CREATE MATERIALIZED VIEW [IF NOT EXISTS] [db.]table_name [ON CLUSTER] [TO[db.]name] [ENGINE = engine] [POPULATE] AS SELECT ...
- 一个物化视图的实现是这样的:当向SELECT中指定的表插入数据时,插入数据的一部分被这个SELECT 查询转换,结果插入到视图中。
创建物化视图的限制
- 创建不带
TO [db].[table]
的物化视图时,必须指定物化视图的 engine 用于数据存储。 - 使用
TO [db].[table]
创建物化视图时,不得使用POPULATE
;(因为会全量跑历史数据)。 - ClickHouse 中的物化视图更像是插入触发器。 如果视图查询中有一些聚合,则它仅应用于一批新插入的数据。 对源表现有数据的任何更改(如更新、删除、删除分区等)都不会更改物化视图。
- 查询语句(select) 可以包含下面的子句:distinct、group by、order by、limit、…,相应的转换是在每个插入数据块上独立执行的。
- 例如,如果设置了
GROUP BY
,则在插入期间聚合数据,但仅在插入数据的单个数据包内。 - 数据不会被进一步聚合。
- 例外情况是使用独立执行数据聚合的
ENGINE
,例如SummingMergeTree
。
- 例如,如果设置了
- 物化视图的 alter 操作有些限制,操作起来不大方便:如果物化视图使用构造
TO [db.]name
,你可以DETACH
视图,为目标表运行ALTER
,然后ATTACH
先前分离的(DETACH
)视图。 - 注意,物化视图受 optimize_on_insert 设置的影响: 在插入视图之前合并数据。
- 物化视图是一种特殊的数据表,可以用 show tables 查看。
物化视图的数据更新
- 物化视图创建好之后,若源表被写入新数据则物化视图也会同步更新。
- POPULATE 关键字决定了物化视图的更新策略:
- 若有 POPULATE,则在创建视图的过程会将源表已经存在的数据一并导入,类似于
create table ... as
; - 若无 POPULATE,则物化视图在创建之后没有数据,只会在创建同步之后写入源表的数据;
- ClickHouse 官方并不推荐使用 POPULATE,因为在创建物化视图的过程中同时写入的数据不能被插入物化视图。
- 若有 POPULATE,则在创建视图的过程会将源表已经存在的数据一并导入,类似于
- 物化视图不支持同步删除,若源表的数据不存在(删除了)则物化视图的数据仍然保留;
- 删除视图,使用DROP VIEW,
DROP TABLE
也适用于视图。
2. 案例实操
- 对于一些确定的数据模型,可将统计指标通过物化视图的方式进行构建,这样可避免查询时重复计算的过程,物化视图会在有新数据插入时进行更新。
准备测试数据
-- 建表语句
create table t_hits(
EventDate Date,
CounterID UInt32,
UserID UInt64,
URL String,
Income UInt8
) engine = MergeTree()
partition by toYYYYMM(EventDate)
order by (CounterID, EventDate, intHash32(UserID))
sample by intHash32(UserID)
settings index_granularity = 8192;
-- 导入一些数据
insert into t_hits select EventDate, CounterID, UserID, URL, Income from datasets.hits_v1 limit 10000;
创建物化视图
-- 创建物化视图语句
create materialized view mv_hits engine = SummingMergeTree
partition by toYYYYMM(EventDate) order by (EventDate, intHash32(UserID))
as select UserID, EventDate, count(URL) as ClickCount, sum(Income) as IncomeSum from t_hits
where EventDate >= '2014-03-20' -- 设置更新点,该时间点之前的数据可以另外通过 insert into select …… 的方式进行插入
group by UserID, EventDate;
- 或者可以用下列语法,表 A 可以是一张 MergeTree 表
CREATE MATERIALIZED VIEW 物化视图名 TO 表 A
AS SELECT FROM 表 B;
- 不建议添加 populate 关键字进行全量更新
导入增量数据
- 向原表导入增量数据,会触发物化视图表的数据更新
insert into t_hits
select EventDate, CounterID, UserID, URL, Income from datasets.hits_v1
where EventDate >= '2014-03-23' limit 10;
-- 查询物化视图
select * from mv_hits;
导入历史数据
- 对于存量的历史数据,可以直接向物化视图表导入增量数据
insert into mv_hits
select UserID, EventDate, count(URL) as ClickCount, sum(Income) as IncomeSum from t_hits
where EventDate = '2014-03-20'
group by UserID, EventDate;
-- 查询物化视图
select * from mv_hits;
MaterializedMySQL 引擎
1. 概述
- MySQL 的用户群体很大,为了能够增强数据的实时性,很多解决方案会利用 binlog 将数据写入到 ClickHouse。为了能够监听 binlog 事件,我们需要用到类似 canal 这样的第三方中间件,这无疑增加了系统的复杂度。
- ClickHouse 20.8.2.3 版本新增加了 MaterializedMySQL 的 database 引擎,该 database 能映射到 MySQL 中的某个 database,并自动在 ClickHouse 中创建对应的 ReplacingMergeTree。ClickHouse 服务做为 MySQL 副本,读取 Binlog 并执行 DDL 和 DML 请求,实现了基于 MySQL Binlog 机制的业务数据库实时同步功能。
特点
- MaterializeMySQL 同时支持全量和增量同步,在 database 创建之初会全量同步 MySQL 中的表和数据,之后则会通过 binlog 进行增量同步。
- MaterializedMySQL database 为其所创建的每张 ReplacingMergeTree 自动增加了 _sign 和 _version 字段。
- 其中,_version 用作 ReplacingMergeTree 的 ver 版本参数,每当监听到 insert、update 和 delete 事件时,在 databse 内全局自增。
- 而 _sign 则用于标记是否被删除,取值 1 或者 -1。
- 目前 MaterializedMySQL 支持如下几种 binlog 事件:
- MYSQL_WRITE_ROWS_EVENT:_sign = 1,_version ++
- MYSQL_DELETE_ROWS_EVENT:_sign = -1,_version ++
- MYSQL_UPDATE_ROWS_EVENT:新数据 _sign = 1
- MYSQL_QUERY_EVENT:支持 CREATE TABLE 、DROP TABLE 、RENAME TABLE 等。
使用细则
- DDL查询:
- MySQL DDL 查询被转换成相应的 ClickHouse DDL 查询(ALTER、CREATE、DROP、RENAME)。
- 数据复制:MaterializeMySQL 不支持直接插入、删除和更新查询,而是将 DDL 语句进行相应转换:
- MySQL INSERT 查询被转换为 INSERT with _sign = 1;
- MySQL DELETE 查询被转换为 INSERT with _sign = -1;
- MySQL UPDATE 查询被转换成 INSERT with _sign = 1 和 INSERT with _sign = -1。
- SELECT查询:
- 如果在 SELECT 查询中没有指定_version,则使用 FINAL 修饰符,返回 _version 的最大值对应的数据,即最新版本的数据。
- 如果在 SELECT 查询中没有指定 _sign,则默认使用 WHERE _sign=1,即返回未删除状态(_sign=1)的数据。
- 索引转换:
- ClickHouse 数据库表会自动将 MySQL 主键和索引子句转换为 ORDER BY 元组。
- ClickHouse 只有一个物理顺序,由 ORDER BY 子句决定。如果需要创建新的物理顺序,请使用物化视图。
2. 案例实操
MySQL 开启 binlog 和 GTID 模式
- 确保 MySQL 开启了 binlog 功能,且格式为 ROW
server-id=1
log-bin=mysql-bin
binlog_format=ROW
- 开启 GTID 模式:如果 clickhouse 使用的是 20.8 prestable 之后发布的版本,那么 MySQL 还需要配置开启 GTID 模式, 这种方式在 mysql 主从模式下可以确保数据同步的一致性(主从切换时)。
gtid-mode=on
enforce-gtid-consistency=1 # 设置为主从强一致性
log-slave-updates=1 # 记录日志
- GTID 是 MySQL 复制增强版,从 MySQL 5.6 版本开始支持,目前已经是 MySQL 主流复制模式。它为每个 event 分配一个全局唯一 ID 和序号,我们可以不用关心 MySQL 集群主从拓扑结构,直接告诉 MySQL 这个 GTID 即可。
- 重启 MySQL
sudo systemctl restart mysqld
准备MySQL表和数据
- 在 MySQL 中创建表并写入数据
create database db_ck_test;
create table `db_ck_test`.`t_dept` (
`id` int(11) not null auto_increment,
`code` int not null,
`name` text default null,
`update_time` datetime default null,
primary key (`id`),
unique key (`code`)
) engine = InnoDB;
insert into `db_ck_test`.`t_dept` (`code`, `name`, `update_time`) values (1000, 'Realinsight', now()), (1001, 'Realindex', now()), (1002, 'EDT', now());
- 再创建一张表
create table `db_ck_test`.`t_user` (
`id` int(11) not null auto_increment,
`code` int,
primary key (`id`)
) engine = InnoDB;
insert into `db_ck_test`.`t_user` (code) values(1);
开启 ClickHouse 物化引擎
set allow_experimental_database_materialized_mysql = 1;
创建复制管道
- ClickHouse 中创建 MaterializeMySQL 数据库
create database test_binlog engine = MaterializedMySQL('192.168.254.132:3306', 'db_ck_test', 'root', '123456');
-- 其中 4 个参数分别是 MySQL 地址、databse、username 和 password
- 查看 ClickHouse 中的数据:
show databases;
use test_binlog;
show tables;
select * from t_dept;
select * from t_user;
修改、删除数据
- 在 MySQL 中修改数据,并在 ClickHouse 日志中查看 binlog 监听时间,并查询 ClickHouse中数据
-- 修改 MySQL 中的数据
update t_dept set name = CONCAT(name,'-v1') where id = 1;
-- 查询ClickHouse
select * from t_dept;
-- 删除 MySQL 中的数据
delete from t_dept where id = 2;
-- 查询ClickHouse
select * from t_dept;
- 在刚才的查询中增加 _sign 和 _version 虚拟字段
select *, _sign, _version from t_dept order by _sign desc, _version desc;
- 在查询时,对于已经被删除的数据,_sign=-1,ClickHouse 会自动重写 SQL,将 _sign = -1 的数据过滤掉。
- 对于修改的数据,则自动重写 SQL,为其增加 FINAL 修饰符。
select * from t_dept;
-- 等价于
select * from t_dept final where _sign = 1;
删除表
- 在 MySQL执行删除表,此时在 clickhouse 处会同步删除对应表,如果查询会报错
-- 在 MySQL 删除表
drop table t_user;
-- 在 ClickHouse 查询
show tables;
select * from t_user;
-- mysql 新建表,clickhouse 可以查询到
create table `db_ck_test`.`t_user` (
`id` int(11) not null auto_increment,
`code` int,
primary key (`id`)
) engine = InnoDB;
insert into `db_ck_test`.`t_user` (code) values(1);
-- 在 ClickHouse 查询
show tables;
select * from t_user;
常见问题排查
1. 分布式 DDL 某数据节点的副本不执行
-
问题:使用分布式 ddl 执行命令
create table on cluster xxxx
某个节点上没有创建表,但是 client 返回正常,查看日志有如下报错。<Error> xxx.xxx: Retrying createReplica(), because some other replicas were created at the same time
-
解决办法:重启该不执行的节点
2. 数据副本表和数据不一致
- 问题:由于某个数据节点副本异常,导致两数据副本表不一致,某个数据副本缺少表,需要将两个数据副本调整一致。
- 解决办法:在缺少表的数据副本节点上创建缺少的表,创建为本地表,表结构可以在其他数据副本通过 show crete table xxxx 获取。
- 表结构创建后,clickhouse 会自动从其他副本同步该表数据,验证数据量是否一致即可。
3. 副本节点全量恢复
- 问题:某个数据副本异常无法启动,需要重新搭建副本。
- 解决办法:清空异常副本节点的 metadata 和 data 目录。从另一个正常副本将 metadata 目录拷贝过来(这一步之后可以启动数据库,但是只有表结构没有数据)。
- 执行
sudo -u clickhouse touch /data/clickhouse/flags/force_restore_data
- 启动数据库
- 执行
4. 数据副本启动缺少 zk 表
-
问题:某个数据副本表在 zk 上丢失数据,或者不存在,但是 metadata 元数据里存在,导致启动异常,报错:
Can’t get data for node /clickhouse/tables/01-02/xxxxx/xxxxxxx/replicas/xxx/metadata: node doesn’t exist (No node): Cannot attach table xxxxxxx
-
解决办法:metadata 中移除该表的结构文件,如果多个表报错都移除
- mv metadata/xxxxxx/xxxxxxxx.sql /tmp/
- 启动数据库
- 手工创建缺少的表,表结构从其他节点 show create table 获取。
- 创建后会自动同步数据,验证数据是否一致。
5. ZK table replicas数据未删除,导致重建表报错
-
问题:重建表过程中,先使用 drop table xxx on cluster xxx,各节点在 clickhouse 上table 已物理删除,但是 zk 里面针对某个 clickhouse 节点的 table meta 信息未被删除(低概率事件),因 zk 里仍存在该表的 meta 信息,导致再次创建该表 create table xxx on cluster,该节点无法创建表(其他节点创建表成功),报错:
Replica /clickhouse/tables/01-03/xxxxxx/xxx/replicas/xxx already exists.
-
解决办法:从其他数据副本 cp 该 table 的 metadata sql 过来。重启节点
6. ClickHouse 节点意外关闭
-
问题:模拟其中一个节点意外宕机,在大量 insert 数据的情况下,关闭某个节点。
-
现象:数据写入不受影响、数据查询不受影响、建表 DDL 执行到异常节点会卡住,报错:
Code: 159. DB::Exception: Received from localhost:9000. DB::Exception: Watching task /clickhouse/task_queue/ddl/query-0000565925 is executing longer than distributed_ddl_task_timeout (=180) seconds. There are 1 unfinished hosts (0 of them are currently active), they are going to execute the query in background.
-
解决办法:启动异常节点,期间其他副本写入数据会自动同步过来,其他副本的建表 DDL 也会同步。
7. 其它问题参考
- https://help.aliyun.com/document_detail/162815.html?spm=a2c4g.11186623.6.652.312e79bd17U8IO
ClickHouse 监控及备份
- ClickHouse 运行时会将一些个自身的运行状态记录到众多系统表中( system.*)。所以我们对于 CK 自身的一些运行指标的监控数据,也主要来自这些系统表。
- 但是直接查询这些系统表会有一些不足之处:
- 这种方式太过底层,不够直观,我们还需要在此之上实现可视化展示;
- 系统表只记录了CH自己的运行指标,有些时候我们需要外部系统的指标进行关联分析,例如 ZooKeeper、服务器 CPU、IO 等等。
- 现在 Prometheus + Grafana 的组合比较流行,安装简单易上手,可以集成很多框架,包括服务器的负载, 其中 Prometheus 负责收集各类系统的运行指标; Grafana 负责可视化的部分。
- ClickHouse 从 v20.1.2.4 开始,内置了对接 Prometheus 的功能,配置的方式也很简单,可以将其作为 Prometheus 的 Endpoint 服务,从而自动的将 metrics、events 和 asynchronous_metrics 三张系统的表的数据发送给 Prometheus。
Prometheus & Grafana 的安装
- Prometheus 下载地址:https://prometheus.io/download/
- Grafana 下载地址:https://grafana.com/grafana/download
1. 安装 Prometheus
- Prometheus 基于 Golang 编写,编译后的软件包,不依赖于任何的第三方依赖。只需要下载对应平台的二进制包,解压并且添加基本的配置即可正常启动 Prometheus Server。
# 下载安装包
wget https://github.com/prometheus/prometheus/releases/download/v2.35.0/prometheus-2.35.0.linux-amd64.tar.gz
# 解压缩
tar -zxvf prometheus-2.35.0.linux-amd64.tar.gz -C /bigdata/install/
cd /bigdata/install/prometheus-2.35.0.linux-amd64
- 修改配置文件:
vim prometheus.yml
,在 scrape_configs 配置项下添加配置
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["node01:9090"]
# 添加 ClickHouse 监控配置
- job_name: "clickhouse-1"
static_configs:
- targets: ["node01:9363"]
- 配置说明:
- global 配置块:控制 Prometheus 服务器的全局配置
- scrape_interval:拉取数据的时间间隔,默认为 1 分钟。
- evaluation_interval:规则验证(生成 alert)的时间间隔,默认为 1 分钟。
- rule_files 配置块:规则配置文件
- scrape_configs 配置块:配置采集目标相关, prometheus 监视的目标。Prometheus 自身的运行信息可以通过 HTTP 访问,所以 Prometheus 可以监控自己的运行数据。
- job_name:监控作业的名称
- static_configs:表示静态目标配置,就是固定从某个 target 拉取数据
- targets: 指定监控的目标,其实就是从哪儿拉取数据。Prometheus 会从 http://node01:9090/metrics 上拉取数据。
- global 配置块:控制 Prometheus 服务器的全局配置
- Prometheus 是可以在运行时自动加载配置的,启动时需要添加:–web.enable-lifecycle。
- 启动 Prometheus Server
# pwd
/bigdata/install/prometheus-2.35.0.linux-amd64
nohup ./prometheus --config.file=prometheus.yml > ./prometheus.log 2>&1 &
- 浏览器访问:http://node01:9090
- 点击 Status,选择 Targets:clickhouse 还没有配置监控,所以状态 State 还是 DOWN 的,后面会进行配置。
2. 安装 Grafana
# 下载安装包
wget https://dl.grafana.com/oss/release/grafana-8.5.2.linux-amd64.tar.gz
# 解压缩
tar -zxvf grafana-8.5.2.linux-amd64.tar.gz -C /bigdata/install/
cd /bigdata/install/grafana-8.5.2
# 启动
nohup ./bin/grafana-server web > ./grafana.log 2>&1 &
- 浏览器访问:http://node01:3000,默认用户名和密码:admin
ClickHouse 配置
1. 修改配置文件
- vim /etc/clickhouse-server/config.xml,开启 prometheus 监控,其它CK节点也需要开启
<prometheus>
<endpoint>/metrics</endpoint>
<port>9363</port>
<metrics>true</metrics>
<events>true</events>
<asynchronous_metrics>true</asynchronous_metrics>
<status_info>true</status_info>
</prometheus>
2. 重启 ClickHouse,并访问
sudo clickhouse restart
- 浏览器访问:http://node01:9363/metrics,能看到如下信息,说明 ClickHouse 开启 Metrics 服务成功。
- 此时访问 prometheus,状态就是 UP 了
Grafana 集成 Prometheus
1. 添加数据源 Prometheus
- 点击配置,选择 Data sources
- 点击添加按钮,并找到 Prometheus,并选择
- 配置 Prometheus Server 地址,并点击下方的 Save&Test
- 出现绿色的提示框,表示与 Prometheus 正常连通
2. 添加监控
- 点击左侧”+“号,选择 Dashboard,选择Add a new panel
- 创建自定义的监控页面
- 手动一个个添加 Dashboard 比较繁琐,Grafana 社区鼓励用户分享 Dashboard,通过 https://grafana.com/dashboards 网站,可以找到大量可直接使用的 Dashboard 模板。
- 搜索 ClickHouse 选择自己想要的模板,这里笔者选用的是这个:https://grafana.com/grafana/dashboards/14432
- Grafana 中所有的 Dashboard 通过 JSON 进行共享,下载并且导入这些 JSON 文件,就可以直接使用这些已经定义好的 Dashboard。
- 点击左侧”+“号,选择 import
- 导入配置模板
- 选择监控来源,并 Import
- 查看监控界面
备份及恢复
- 官方文档:https://clickhouse.com/docs/en/operations/backup/
1. 手动实现备份及恢复
- ClickHouse 允许使用
ALTER TABLE ... FREEZE PARTITION ...
查询以创建表分区的本地副本。这是利用硬链接(hardlink)到/var/lib/clickhouse/shadow/
文件夹中实现的,所以它通常不会因为旧数据而占用额外的磁盘空间。 创建的文件副本不由 ClickHouse 服务器处理,所以不需要任何额外的外部系统就有一个简单的备份。防止硬件问题,最好将它们远程复制到另一个位置,然后删除本地副本。 - 创建备份路径:
# 创建用于存放备份数据的目录 shadow,如果目录存在,先清空目录下的数据
sudo mkdir -p /var/lib/clickhouse/shadow
chown -R clickhouse:clickhouse shadow/
- 执行备份命令:
echo -n 'alter table test.t_order_mt freeze' | clickhouse-client --password
Password for user (default): 输入密码
- 将备份数据保存到其它路径:
# 创建备份存储路径
sudo mkdir -p /var/lib/clickhouse/backup
# 拷贝数据到备份路径
sudo cp -r /var/lib/clickhouse/shadow/ /var/lib/clickhouse/backup/test.t_order_mt.bak
# 为下次备份准备,删除 shadow 下的数据
sudo rm -rf /var/lib/clickhouse/shadow/*
- 恢复数据:
# 删除备份过的表
echo 'drop table test.t_order_mt' | clickhouse-client --password
Password for user (default): 输入密码
# 重新创建表
cat test.t_order_mt.sql | clickhouse-client --password
# 将备份复制到 detach 目录
sudo cp -rl /var/lib/clickhouse/backup/test.t_order_mt.bak/1/store/c1d/c1d638d1-0fe4-4a9e-b00c-fc7a0b0a1f6a/* /var/lib/clickhouse/data/test/t_order_mt/detached/
chown -R clickhouse:clickhouse /var/lib/clickhouse/data/test/t_order_mt/detached/
- ClickHouse 使用文件系统硬链接来实现即时备份,而不会导致 ClickHouse 服务停机(或锁定)。这些硬链接可以进一步用于有效的备份存储。在支持硬链接的文件系统(例如本地文件系统或 NFS)上,将 cp 与-l 标志一起使用(或将 rsync 与–hard-links 和–numeric-ids 标志一起使用)以避免复制数据。
- 注意:仅拷贝分区目录,目录所属的用户要是 clickhouse。
- 执行 attach:
echo 'alter table test.t_order_mt attach partition 20220415' | clickhouse-client --password
- 查看数据:
echo 'select * from test.t_order_mt' | clickhouse-client --password
2. 使用 clickhouse-backup
- 上面的过程,我们可以使用 Clickhouse 的备份工具 clickhouse-backup 帮我们自动化实现。
- 下载安装:
# 下载最新版 rpm 包
wget https://github.com/AlexAkulov/clickhouse-backup/releases/download/v1.3.2/clickhouse-backup-1.3.2-1.x86_64.rpm
# 安装
sudo rpm -ivh clickhouse-backup-1.3.2-1.x86_64.rpm
- 修改配置文件:修改下默认用户登录密码,其它的都不用改
cd /etc/clickhouse-backup/
cp config.yml.example config.yml
vim config.yml
- 查看
clickhouse-backup
命令:
# 查看可用命令
clickhouse-backup help
NAME:
clickhouse-backup - Tool for easy backup of ClickHouse with cloud support
USAGE:
clickhouse-backup <command> [-t, --tables=<db>.<table>] <backup_name>
VERSION:
1.3.2
DESCRIPTION:
Run as 'root' or 'clickhouse' user
COMMANDS:
tables Print list of tables # 显示要备份的表
create Create new backup # 创建新的备份
create_remote Create and upload
upload Upload backup to remote storage
list Print list of backups # 查看现有的本地备份
download Download backup from remote storage
restore Create schema and restore data from backup
restore_remote Download and restore
delete Delete specific backup
default-config Print default config
print-config Print current config
clean Remove data in 'shadow' folder from all `path` folders available from `system.disks`
server Run API server
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--config FILE, -c FILE Config FILE name. (default: "/etc/clickhouse-backup/config.yml") [$CLICKHOUSE_BACKUP_CONFIG]
--help, -h show help
--version, -v print the version
- 创建备份:
- 备份存储在中
/var/lib/clickhouse/backup/BACKUPNAME
。备份名称默认为时间戳,但是可以选择使用–name
标志指定备份名称。 - 备份包含两个目录:
- 一个 metadata 目录,其中包含重新创建架构所需的 DDL SQL 语句;
- 以及一个 shadow 目录,其中包含作为 ALTER TABLE … FREEZE 操作结果的数据。
- 备份存储在中
# 先将原来手动备份的数据删掉
rm -rf /var/lib/clickhouse/backup/*
# 执行创建备份
clickhouse-backup create
- 从备份恢复数据:
- –schema 参数:只还原表结构。
- –data 参数:只还原数据。
- –table 参数:备份(或还原)特定表。也可以使用一个正则表达式,例如,针对特定的数据库:–table=dbname.*。
# 删除备份过的表
echo 'drop table test.t_order_mt' | clickhouse-client --password
Password for user (default): 输入密码
# 从备份还原
clickhouse-backup restore 2022-05-06T22-55-20clickhouse-backup restore 2022-05-06T22-55-20 --table test.t_order_mt
- 其它说明:
- API 文档:https : //github.com/AlexAkulov/clickhouse-backup#api
- 注意事项:切勿更改文件夹/var/lib/clickhouse/backup 的权限,可能会导致数据损坏。
- 远程备份:
- 较新版本才支持,需要设置 config 里的 s3 相关配置
- 上传到远程存储:sudo clickhouse-backup upload xxxx
- 从远程存储下载:sudo clickhouse-backup download xxxx
- 保存周期:
- backups_to_keep_local,本地保存周期,单位天
- backups_to_keep_remote,远程存储保存周期,单位天
- 0 均表示不删除