简介
ClickHouse 是一款优秀的 OLAP 分析引擎,尤其是在单表分析 、Colocate Join 方面性能表现尤为突出。ClickHouse 之所以在众多的 OLAP 分析引擎中成为佼佼者,主要是因为它具备以下特点:列式存储、LSM-Tree 存储引擎、向量化执行引擎、异步 Merge 和 Mutation 机制、并发 MPP+ SMP 等。
目前,ClickHouse 在苏宁大数据的指标和标签的应用较多,从技术层面来看,主要解决的场景有:高基数的数据分析、精确去重、交互式分析、多变模式查询、大宽表分析、时序化数据存储、实时聚合的物化视图等。从业务层面来看,主要应用的场景有:新买家、老买家、复购、留存、实时用户画像、人群包圈选等。而基于 ClickHouse 的 RoaringBitmap 方案,保证了以上场景数据分析的实时和高效。
在 ClickHouse 监控方面,目前市面上提供的可适配方案不多,常用的有 Prometheus +Grafana+ClickHouse_Exporter 组合的方式,可通过提供的 Dashboards 来监控集群状况,但需要安装 Prometheus 和 ClickHouse_Exporter,不编译的话还需要安装 GO 环境和 Docker,整个框架过重,成本过高,对个性化的监控也不支持。还有一些其他监控组件如 Graphite + Grafana,在这里就不做介绍。我们将 ClickHouse 融入苏宁全链路监控生态体系,在完善监控体系的同时,也支撑了个性化的监控,进一步拓展了全链路监控平台的深度和广度。
苏宁大数据全链路监控平台
1. 苏宁全链路监控平台介绍
图 2-1 全链路监控架构
苏宁大数据中心数据中台有一整套完善的指标建设体系,包含了指标生命周期管理、指标分析体系以及数据快速可视化平台,数据分析时跨越可视化平台、指标服务平台及 OLAP 分析引擎三大平台,查询链路较长,如果没有一套完整的全链路监控分析平台,对于定位问题会存在较大的困难。全链路监控整体的设计思想是将页面的每次 http 请求生成唯一的流水号(serialId),后续每访问一次指标管理系统,生成唯一的 traceId,每次调用 OLAP 接口生成唯一的 olapId,这样就形成 1 个流水号对应多个 traceId,关联对应后续多个 olapId,形成一个树状请求,得到一个完整的请求链路。
具体设计如下:
(1)报表设计系统后端针对报表前端的每次请求生成唯一 traceId,针对请求的每一步生成层级关系的 spanId,并向指标管理系统透传 traceId 和对应的 spanId。
(2)指标管理系统接受请求后,根据梳理的查询权重计算方式生成“查询权重”priority,在报表设计系统的 spanId 基础上继续生成调用层级关系的 spanId,并向 OLAP 透传 traceId 和对应的 spanId。
(3)Spark RDD 实现将 Druid、PostGreSQL 和 ClickHouse 中的 queryId 与 Spark worker 中的 StageID 以及 JobID 关联起来。
(4)OLAP 接受请求后,在指标管理系统的 spanId 基础上继续生成调用层级关系的 spanId,并向 OLAP 引擎层透传 traceId 和对应的 spanId。
(5)OLAP 分析引擎层,通过打通 traceId 和各自分析引擎执行路径的方式,实现跟踪各执行计划、执行路径的耗时。例如,可通过 bigQueryId 与 Druid 关联,而 PostGreSQL 和 ClickHouse 则可以通过 traceId 映射到引擎内部的方式进行关联。
2. 如何实现将 ClickHouse 纳入到全链路监控平台
ClickHouse 全链路监控覆盖范围较广,包括:查询涉及到的节点、分片、父查询和子查询的关系、在各个节点的查询耗时、请求内存使用、高峰使用内存、CPU 使用数、查询行数、MergeTree 使用状况、查询方式(TCP/HTTP)以及参与查询线程数等。
在调用 ClickHouse 提供服务查询(spark-jdbc)的时候,如何将 traceId 透传给 ClickHouse 的 query_id 呢?
实现全链路监控,主要是通过 traceId 贯穿整个链路。表 system.processes 和表 system.query_log 中的 query_id 是随机生成的,ClickHouse 的 query_id 支持自定义,可将自定义的 query_id 映射到系统自生成的 query_id 上,这样 ClickHouse 内部的监控就能与全链路打通,具体操作如下:
ClickHouse 慢查询监控
1. 实时慢查询监控
图 3-1 实时慢查询监控
父节点查询 ID(initial_query_id)是从上游系统传入的 traceId,此次查询的所有子查询均可根据 traceId 获取,可以实时分析某次查询在集群中各个节点的状态,其中包括查询 query_id 的父子关系及对应的节点信息、各个节点的查询脚本、查询耗时、读取的行数、请求使用的内存、高峰使用的内存、参与查询的线程数、user、ProfileEvents、Settings 等。
图 3-2 单次查询内存/CPU/MergeTree/耗时 TOPN 监控
图 3-2 展示各集群中的慢查询 TOPN、单次查询内存使用 TOPN、单次查询 CPU 使用数 TOPN、MergeTree 耗时 TOPN,支持对超过预期阈值的查询进行告警。
2. 历史慢查询监控
图 3-3 历史慢查询监控
(1)ClickHouse 默认的情况下 query_log 表是未开启的状态,必须将其开启,修改配置文件 users.xml,路径为/etc/clickhouse-server/,新增配置项<log_queries>1</log_queries>,当查询日志服务器参数log_queries=1 时,ClickHouse 才会创建此表。
(2)每个查询在 query_log 表中会创建一条或两条记录,具体取决于查询的状态:
如果查询执行成功,则会分别创建事件类型为1和2的两条记录;
如果在查询处理期间发生错误,则会分别创建事件类型为1和4的两条记录;
如果在查询启动之前发生错误,则会创建事件类型为3的单条记录。
(3) 表 query_log 中的记录,存储的是历史查询在集群中的各个节点的状态,其中包括查询 query_id 的父子关系及对应的节点信息、各个节点的查询脚本、查询开始时间、查询日期、查询时间、查询耗时、查询行数、查询结果的字节大小、请求使用的内存、高峰使用的内存、参与查询的线程数、堆栈跟踪以及查询异常信息等。
3. MergeTree 监控
图 3-4 MergeTree 基础表引擎
MergeTree 表中数据存储在 Part 中,当插入数据的时候,会将数据创建在一个新的 Part 中,Part 的数量代表着提交的频率。后台会进行异步的 Merge 过程,将小的 Part 进行合并,并且会相对均衡的平衡好合并速度和 Part 数量的关系。对于每个 Part 均会生成一个索引文件,索引文件存储的是每个索引块数据主键的 value 值。对于 MergeTree 的监控,主要监控 MergeTree 的异常情况,根据异常信息进行告警。
4. 慢查询归因分析
通过以上的监控,可以快速定位出慢查询。导致慢查询的原因可能有很多,可以从如下几个方面进行分析:
1)判断查询的数据是否存在 page cache 中,从 page cache 获取数据速度远高于磁盘。
2)高基数的聚合或排序对查询效率影响较大,JOIN 操作时应将小表放右边,分区字段不宜过多,导入数据时候最好对数据进行事先排序。
3)影响性能最关键的指标是 CPU 和内存,CPU 超过 70%则可能会出现大范围的查询超时。另外需要关闭虚拟内存,否则物理内存和虚拟内存可能会进行数据交换,从而导致查询变慢。
4)ClickHouse 对高并发支持不太友好,需要对单个查询的资源加以限制,否则会影响当前其它查询的执行效率。
以上是常规的慢查询原因分析,而有些复杂、高基数的查询可通过巧妙的设计方式,达到高效查询的目标。我们在基于 ClickHouse 计算会员新买家、老买家数、复购、留存等场景的时候发现,如果用会员 ID 进行 HASH 分片后再做 RoaringBitmap 计算,最后再将每个分片的计算结果汇总,其执行效率将提高数倍。另外在计算纯新买家和次新买家的时候,通过在子查询中使用 ClickHouse-CTE 的 WITH 方式,同样可以达到实时、高效的查询目标。
ClickHouse 集群状态监控
1. 集群、节点状态监控
可对集群、节点的查询状态进行监控,如成功次数、异常次数和失败次数,并且根据设定的阈值对失败或超时的查询进行预警。同时可对各个节点的连接数、CPU 使用率、内存使用率、FileOpen、根分区使用率以及最大分区使用率进行监控。
2. 集群、节点、分片 QPS 和连接数监控
图 4-1 集群、节点、分片 QPS 监控
图 4-2 集群、节点、分片连接数监控
ClickHouse 的计算和存储是一体式的,并未做资源隔离,为了提高系统的并发能力,可以将数据保存为多个副本,每个副本部署到不同的节点上,再通过 Chproxy 路由到不同的节点进行查询。为了保证集群的持续稳定、可用,需要对单个查询的资源以及集群最大支持的并发进行限制,具体方式如下:
1)集群同时支持的最大并发连接数可通过 Max_Concurrent_queries 来设置,默认为 100。
2)一个查询在单台服务上最大使用的内存可通过 Max_memory_usage 来设置。
3)单个节点上所有查询的最大内存限制是可通过 Max_memory_usage_for_all_queries 来设置。
4)单次查询的最长执行时间可通过 Max_execution_time 来设置。
3. 集群、节点、分片可用性监控
具体可以通过 HTTP API 监视服务器的可用性来实现。通过 HTTP GET 请求后,如果服务器可用,则返回 200 OK,否则返回异常消息。此处需要有个告警配置监控项,一旦监测到节点不可用,可及时通知相关技术人员进行维护,其中告警信息可通过短信、邮件等方式进行推送。
4. 全链路 Replicas Delay 监控
图 4-3 Replicas Delay 监控
(1)Random 分布式随机选取副本有四种算法:
Random:选取副本的默认方式,该算法主要是通过计算副本的错误数量,查询发送到出错最少的副本,但这种算法没有考虑到服务节点是否相邻的场景。
In order:选取副本的方式是根据配置中指定的顺序。
First or random:选择集合中第一个副本,如果第一个副本不可用,则随机进行副本选择。
Nearest hostname:每隔5分钟计算副本的错误数量,如果副本的错误数量最少,则将查询发送给它。
(2)副本允许的最长延迟时间,可通过参数 max_replica_delay_for_distributed_queries 来设置;副本的延迟时间,可以使用 HTTP resource /replicas-delay 来查询,不延迟则返回 200 OK,延迟则返回和默认时间的差距。
5. 全链路 Chproxy 监控信息
图 4-4 ClickHouse Manger 工作流程
ClickHouse 的 Http 代理和负载均衡器是 Chproxy,苏宁通过 ClickHouse Manger 来管理 Chproxy 组件的启动、停止、滚动升级以及监控,并通过 ZK 向 Chproxy 同步配置数据。ClickHouse 集群可以部署多个 Chproxy 实例,客户端连接 ClickHouse 集群的代理服务后,通过对查询 SQL 解析,智能的进行负载均衡。同时,Chproxy 也支持水平扩展。
Chproxy 能监控到的重点指标有:集群请求队列大小、远程客户端连接数、查询总请求数、取消请求数、被拒绝请求数、缓存命中情况、集群和节点健康状态等,苏宁全链路监控平台可对上述重点指标进行监控。
全链路监控的优势和展望
全链路监控平台拓展了我们监控系统能力的深度和广度,同时为 ClickHouse 的资源隔离和服务化提供了参考。全链路监控平台目前已经将数据应用层、SparkSQL 解析层、OLAP 路由加速层以及数据加速层全部贯穿,用户发起的请求在各个阶段的耗时一目了然。我们能把各个 OLAP 分析引擎内部执行的耗时,通过统一的 queryId 纳入到苏宁全链路监控平台,形成一条完整的执行耗时监控链路。各阶段预设的超时预警,会在第一时间通知相关责任人,这种方式对问题定位、主动预警都起到了重要的作用,同时给监控运维带来了极大的便利。
在 OLAP 路由层,我们已经对接了 Druid、Elasticsearch、PostGreSQL 以及 ClickHouse 分析引擎,后续我们将对接其它更多的 OLAP 分析引擎,如 Doris、Dremio 和 RocksDB 等,同时我们也将持续细化、分析各引擎内部执行阶段的耗时情况,对全链路监控能力进行更进一步的优化提升。
作者介绍:
范东,苏宁科技集团大数据中心资深架构师,在 OLAP、OLTP 领域有着深厚的技术积累。目前主要负责数据中台和数据工具平台的架构设计及性能调优工作,在数据中台、数据集成开发工具、数据资产、数据质量和数据治理等方面拥有丰富的实战经验。
评论 8 条评论