ClickHouse 创建表时是支持表级数据 TTL 策略的,TTL 策略可以支持数据过期自动合并 (Compaction) 后删除,当然也支持自动合并后移动到其他 Disk 或 Volumn。日志平台的多级存储就是利用了存储策略,但由于踩了 TTL 的一个坑,我们最终放弃表级 TTL 设置,改成搬迁表 part 的任务调度实现 TTL 策略,后面会说到。
- 配置存储策略
<path>/data1/ClickHouse/data/</path> --为了便于查找,我们建议在默认的存储路径下方添加存储策略
<storage_configuration>
<disks>
<hot>
<path>/data1/ClickHouse/hot/</path> --这里注意,使用存储策略后,建议任何数据路径之间不要有子集关系
</hot>
<cold>
<path>/data2/ClickHouse/cold/</path>
</cold>
</disks>
<policies>
<ttl>
<volumes>
<hot>
<disk>hot</disk>
</hot>
<cold>
<disk>cold</disk>
</cold>
</volumes>
</ttl>
</policies>
</storage_configuration>
-
<path> 为 ClickHouse 默认的存储路径,找到该标签后在下方添加存储策略标签 < storage_configuration>。
-
<storage_configuration>:固定标签,定义存储策略。 - <dicks> 固定标签,下面会定义磁盘名称,以及磁盘绝对路径。 - <hot>、<cold>:自定义标签,用来标记该路径,可按照此名称定义便于区分。 - <policies>:固定标签,定义具体存储策略名称。 - <ttl>:自定义标签,定义具体存储策略的名称,用于表级 TTL,可按照此名称定义便于区分。 - <volumes>:固定标签,定义卷组。 - <hot>、<cold>:卷组名称,每个卷组下可以包括一个或多个 disk 标签,disk 标签取值为 < disks > 标签下定义的磁盘名称。
-
创建表
示例:
CREATE TABLE db_rdsauditlog_local ON CLUSTER auditlog
(
`check_rows` Int64,
`client_ip` String,
`db` String,
`fail` Int64,
`instance_id` String,
`latency` Int64,
`origin_time` DateTime('Asia/Shanghai'),
`return_rows` Int64,
`sql` String,
`thread_id` Int64,
`update_rows` Int64,
`user` String,
`tables` Array(String),
`sqlhash` String,
`sqlfingerprint` String,
`sqltype` String,
INDEX instance_sqltype (instance_id, sqltype) TYPE set(100) GRANULARITY 5,
INDEX origintime_sqlhash (instance_id,sqlhash) TYPE set(100) GRANULARITY 5,
INDEX origintime_instance_clientip(instance_id, client_ip) TYPE set(100) GRANULARITY 5
)
ENGINE = MergeTree
PARTITION BY toYYYYMMDD(origin_time)
ORDER BY origin_time
TTL origin_time + INTERVAL 6 hour TO DISK 'cold'
SETTINGS storage_policy = 'ttl',index_granularity = 8192;
Create table db_rdsauditlog on cluster auditlog as db_rdsauditlog_local ENGINE=Distributed(auditlog, default, db_rdsauditlog_local, rand());
创建表级 TTL ,要想使用分级冷热存储,必须要指定存储策略,才能使用到 Disk ,为什么要指定存储策略,我的理解是 TTL 可以指定到 Disk 和 Volumn 级,但是 Volumn 级别只能定义在存储策略里。
具体阅读:https://ClickHouse.com/docs/en/engines/table-engines/mergetree-family/mergetree#mergetree-table-ttl
2.3 分区策略
PARTITION BY-- 分区键,表级可选的参数。在大多数情况下,其实不需要分区键,同时即便使用了分区键,不太建议使用比月更细粒度的分区键,分区不会加速查询(与 ORDER BY 表达式相反)。你永远不应该使用太细化的分区。不要按客户端标识符或名称对数据进行分区,而是将客户端标识符或名称作为 ORDER BY 表达式中的第一列 (官方文档这句话还是要好好牢记,一般我们只建议时间字段做分区)。
以上是官方文档的原话,但是实际中我们需要根据具体情况是可以创建甚至到小时级别粒度的分区,还是那句话,看需求,用不好会有副作用,后面会提到。
3. 业务需求
业务背景中除了提到需要很高的写入能力,很高的压缩比,实际需求调研中,基础架构同学还提出各个业务域都有自己的日志时间查询范围需求 (ES 作为存储时,研发甚至需要能够提供天级的日志保留时间),比如 7 天,30 天,90 天,甚至更长等不同范围,因为冷数据查询频次较低,可以使用更低廉的存储介质,另外有一些数据保留一段时间之后不会被查但需要满足合规要求,再长的日志就可以删除。基础架构希望 DBA 能够帮忙在 ClickHouse 的存储上对数据保留时间提供一些建议,尽最大可能降低存储成本。
总结一下就是如下需求:
- 如何能尽可能满足各个业务域的天级保留策略?
- 如何将数据能够根据日期存放在不同的存储介质中?
- 多级存储策略选用什么样的存储介质能够尽最大可能降低存储成本?
根据这些需求,DBA 对这些需求提供了如下方案:
- 天级保留策略,我们使用了表分区策略,并规避了一些坑。
- 多级存储主要使用了三级存储策略,即 Hot+Cold+Arch (Archive 后续均已 Arch 代替)。
- Hot 盘选用 ESSD PL1 盘挂载宿主机,磁盘名称为 hot;Cold 选用 ESSD PL0 盘挂载宿主机,磁盘名称为 cold;Arch 我们最终选择直接挂载 OSS 文件系统 (因为中间我们还调研过 JuiceFS,但最终还是放弃了),磁盘名称为 arch。