前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CK04# ClickHouse日志存储调优总结

CK04# ClickHouse日志存储调优总结

作者头像
瓜农老梁
发布2022-12-03 09:24:22
9640
发布2022-12-03 09:24:22
举报
文章被收录于专栏:瓜农老梁

引言

随着ClickHouse日志存储上线,开启替换ElasticSearch的切换过程,是时候为过去一段时间ClickHouse各种尝试做个总结。本文的主要内容有:

  • 集群规模与调优
  • 表结构设计要点
  • 其他设计点补充

一、集群规模与调优

一个集群多少节点,节点使用什么样的配置,总共需要多少个集群。

在规划时首先需要考虑的,并在实践中也需要相互验证与调整。

使用冷热分离架构,一个节点挂2T的热盘以及5T的冷盘。

每个节点热盘使用SSD,冷盘使用普通盘。

笔者一个ClickHouse集群部署了20个节点。

1、集群规模

日志存储划分为几个集群,有的公司会将所有的日志存储在一个集群。

根据公司情况将ClickHouse集群划分了4个,具体规模需要根据实际情况评估。

集群一:存储支撑域相关日志。

集群二:存储非交易业务日志。

集群三:存储交易相关日志。

集群四:存储算法推荐相关日志。

备注1:划分为多个集群,可根据不同的业务域方便针对性的治理。

备注2:一个集群有问题时方便将日志流量调度到其他日志集群应急处理。

2、集群配置

2.1 集群配置一

刚开始规划使用16C64G的配置,然而查询确遇到了问题,无法投产。

测试精确查找一条日志,需要30秒。

模糊查询一条最近5小时内的日志,需要60秒。

备注1:投产需要查询耗时无明显的等待感,5秒内为宜。

备注2:小部分超过5秒也可以接受,否则无法在生产环境投入使用。

2.2 集群配置二

后来通过与业内ClickHouse专家与公司同事反复沟通与对焦,将配置提升到48C192G。

精确查找一条日志,几百毫秒返回

布隆查询一条最近5小时内的日志,秒级返回

模糊查询一条最近5小时内的日志,3秒内返回

备注1:该配置基本满足了业务支撑类场景的使用

备注2:然对于推荐算法这种高吞吐、大消息(高达20KB一条)依然不能解决

2.3 集群配置三

针对算法推荐场景针对性治理,单条消息20KB左右,吞吐也很高。

首先是升盘将SSD PL1升级到PL2,进一步提高IOPS吞吐,然而依然存在问题。

模糊查询一条最近5小时内的日志,整个集群IPOS被打满,耗时超过30秒,无法投产。

进一步提高磁盘配置,将PL2升级为PL3,对应的配置也提高128C256G。

模糊查询一条最近5小时内的日志,大部分3~5内返回。

模糊查询一条最近1小时内的日志,大部分2内返回。

精确查找一条日志消息,大部分1秒左右返回。

备注:查询基本都在5秒内,没有特别明显的等待感,具备上线条件。

3、集群调优

除了集群规模、集群配置外,集群调优也很重要。

ClickHouse有几个参数需要调优,如下:

参数

说明

示例

硬件配置

硬件配置至关重要,过低配置无法投产

48C192G/热盘SSD 2T/冷盘HDD 5T * 20

max_threads

用于控制一个用户的查询线程数

可配置核数的80%,例如:40C

max_memory_usage

单个查询最多能够使用内存大小

可配置内存的80%,例如:80G

max_execution_time

单个查询最大执行时间

根据实际设置,例如:60查询耗时不超过1分钟

skip_unavailable_shards

当某一个shard无法访问时,其他shard的数据仍然可以查询

例如:设置1

小结:根据不同业务场景划分多个集群,方便针对性调优治理,当然集群规模也不易过多,灵活权衡。

二、表结构设计要点

表结构的设计也至关重要,笔者团队在不断尝试时,表结构推了重来次数不下5次,不断调整提高查询性能。

1、重视字段索引创建

将公共约定的常用名称,独立成字段,方便添加索引,提升查询效率。

例如:链路ID设置为String类型,String类型的字段trace_id添加索引:

代码语言:javascript
复制
`tracing_id` String,
INDEX tracing_id tracing_id TYPE SET(100) GRANULARITY 2,
INDEX idx_tracing_id tracing_id TYPE tokenbf_v1(512, 2, 0) GRANULARITY 2

时间类型的字段record_time添加索引:

代码语言:javascript
复制
`record_time` DateTime64(3),
INDEX record_time record_time Type minmax GRANULARITY 2

备注1:ClickHouse的MergeTree提供了4种类型的跳数索引(二级索引)。

备注2:4中类型跳数索引为:minmax、set、ngrambf_v1和tokenbf_v1。

备注3:充分为字段建立索引提高查询性能,只要能提高查询性能均可尝试。

备注4:笔者甚至为String类型的字段使用Set和tokenbf_v1两种类型的索引。

2、合理选择分区字段

选择什么样的分区字段是非常重要的,直接影响集群的整体性能。

笔者在此过程中也反复尝试了多种方式。

2.1 应用和天分区

是指每个应用每天一个分区,也方便各个应用的日志成本的核算和分摊。

通过测试存在以下问题:

几百个应用意味着一天有几百个分区。

Flink在写入时导致ClickHouse的整体IOPS居高不下。

严重时写入的IPOS占整体的30%以上,甚至50%。

备注:写入占用了过多的磁盘IOPS资源,严重影响查询性能,需要将更多的CPU/IO资源留个查询。

2.2 按天设置分区

是指一个集群的所有应用共用一个分区,每天创建一个。

通过测试有效降低磁盘IOPS。

为了能够根据分摊存储成本,将消息提大小、存储时长,提成独立字段解决。

分区字段示例

代码语言:javascript
复制
PARTITION BY (toDate(log_time),log_save_time)  

备注:按天分区能解决绝大多数业务日志,然而凡事总有例外。

2.3 按小时设置分区

按天分区在业务场景能满足需求,也降低了写入的IPOS。

然而在数据智能算法推荐场景,由于其日志量和消息大小均很大。

尽管将分区的迁移放在了凌晨2点之后,一个分区一个分区迁移。

当一个分区迁移时把整个集群的IPOS打满,而且是持续打满。

对半夜日志排查造成严重困扰,所以决定对该集群使用按小时创建分区。

代码语言:javascript
复制
PARTITION BY (toStartOfHour(log_time),log_save_time)  

备注:根据业务实际场景,灵活定制设置分区键,针对性优化提高性能。

3、合并树引擎与排序字段

笔者在生产环境使用了MergeTree,而没有采用ReplacingMergeTree。

尽管日志可能重复数据,然而合并相同数据必然消耗集群性能。

一切都在取舍之中,一切让位与集群性能。

排序字段尽可能是查询的字段,充分利用主键索引。

代码语言:javascript
复制
ORDER BY (application, environment, log_time, ip, file_offset)

备注:选择合适的合并树引擎、利用好排序字段和主键索引。

4、选择合适的压缩算法

更强悍的压缩算法,往往需要牺牲一定的性能为代价。

CK的压缩算法LZ4和ZSTD也不例外。

经测试LZ4查询响应要比ZSTD快30%左右。

LZ4的磁盘占用空间要比ZSTD多2.5倍左右。

LZ4的压缩比约为1:4,ZSTD的压缩比约为1:10。

如果使用LZ4查询耗时为1秒,而ZSTD查询性能为1.5秒左右。

秒级的影响对使用方来说,体感并不明显,高达2.5倍的存储开销,确耗费不少。

ZSTD压缩示例

代码语言:javascript
复制
`message` String  CODEC(ZSTD),
INDEX idx_message message TYPE tokenbf_v1(512, 2, 0) GRANULARITY 2,

备注:选择合适的压缩算法,笔者更倾向经济实用型,会选择ZSTD压缩算法。

三、其他设计点补充

下面是简化版本的demo创建表语句。

代码语言:javascript
复制
CREATE TABLE demo_log_local on cluster default
(
    `app` String,
    `keyArr` Array(Nullable(String)),
    `valArr` Array(Nullable(String)),
    `msgBody` String  CODEC(ZSTD),
    `record_time` DateTime64(3),
    `tracing_id` String,
    `storage_time` Int32,
    `msg_size`  Int64,  
    INDEX msg_size msg_size TYPE SET(100) GRANULARITY 2,
    INDEX app app TYPE SET(100) GRANULARITY 2,
    INDEX msgBody msgBody TYPE tokenbf_v1(32768, 2, 0) GRANULARITY 2,
    INDEX idx_msgBody msgBody TYPE tokenbf_v1(512, 2, 0) GRANULARITY 2,
    INDEX tracing_id idx_tracing_id TYPE SET(100) GRANULARITY 2,
    INDEX idx_tracing_id idx_tracing_id TYPE tokenbf_v1(512, 2, 0) GRANULARITY 2,
    INDEX record_time record_time Type minmax GRANULARITY 2
)
ENGINE = MergeTree
PARTITION BY (toDate(record_time),storage_time)  
ORDER BY (application, record_time)
SETTINGS allow_nullable_key = 1, storage_policy = 'ttl', index_granularity = 8192

在使用flink写入ClickHouse日志时,可以留有20%的余量,避免高峰期积压。

ClickHouse本身的运维、监控白屏化、告警配置、可视化查询控制台等。

小结:总之,从不同点触发去优化,让ClickHouse具备线上投产能力,把成本降下来的同时,不过度对使用造成影响。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 瓜农老梁 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、集群规模
  • 2、集群配置
    • 2.1 集群配置一
      • 2.2 集群配置二
        • 2.3 集群配置三
        • 3、集群调优
        • 1、重视字段索引创建
        • 2、合理选择分区字段
          • 2.1 应用和天分区
            • 2.2 按天设置分区
              • 2.3 按小时设置分区
              • 3、合并树引擎与排序字段
              • 4、选择合适的压缩算法
              相关产品与服务
              对象存储
              对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档