登录  | 加入社区

黑狼游客您好!登录后享受更多精彩

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

查看: 514|回复: 0

云数据库ClickHouse资源隔离-弹性资源队列

[复制链接]

959

主题

959

帖子

0

现金

黑狼菜鸟

Rank: 1

积分
0
发表于 2020-12-24 03:42:25 来自手机 | 显示全部楼层 |阅读模式 来自 法国

原标题:云数据库ClickHouse资源隔离-弹性资源队列

弁言:ClickHouse内核分析系列文章,本文将为各人深度解读ClickHouse当前的MPP盘算模子、用户资源隔离、查询限流机制,在此底子上为各人先容阿里巴巴云数据库ClickHouse在八月份即将推出的自研弹性资源队列功能。ClickHouse开源版本当前还没有资源队列相干的规划,自研弹性资源队列的初志是更好地办理隔离和资源使用率的题目。下文将从ClickHouse的MPP盘算模子、现有的资源隔离方案睁开来看ClickHouse当前在资源隔离上的痛点,末了为各人先容我们的自研弹性资源队列功能。

MPP盘算模子

在深入到资源隔离之前,这里有须要简朴先容一下ClickHouse社区纯自研的MPP盘算模子,由于ClickHouse的MPP盘算模子和成熟的开源MPP盘算引擎(比方:Presto、HAWQ、Impala)存在着较大的差别(que xian),这使得ClickHouse的资源隔离也有一些独特的要求,同时盼望这部门内容能引导用户更好地对ClickHouse查询举行调优。

ClickHouse的MPP盘算模子最大的特点是:它压根没有分布式实行筹划,只能通过递归子查询和广播表来办理多表关联查询,这给分布式多表关联查询带来的题目是数据shuffle爆炸。别的ClickHouse的实行筹划天生过程中,仅有一些简朴的filter push down,column prune规则,完全没有join reorder本领。对用户来说就是"所写即所得"的模式,要求大家都是DBA,下面将联合简朴的查询例子来先容一下ClickHouse盘算模子最大的几个原则。

递归子查询

在阅读源码的过程中,我可以感受到ClickHouse前期是一个完全受母公司Yandex搜刮分析业务驱动发展起来的数据库。而搜刮业务场景下的Metric分析(uv / pv ...),对分布式多表关联分析的并没有很高的需求,绝大部门业务场景都可以通过简朴的数据分表分析然后聚合效果(数据建模比力简朴),以是从一开始ClickHouse就注定不擅优点理复杂的分布式多表关联查询,ClickHouse的内核只是把单机(单表)分析做到了性能极致。但是任何一个业务场景下都不能完全制止分布式关联分析的需求,ClickHouse接纳了一套简朴的Rule来处置惩罚多表关联分析的查询。

对ClickHouse有所相识的同砚应该知道ClickHouse接纳的是简朴的节点对等架构,同时不提供任何分布式的语义包管,ClickHouse的节点中存在着两种范例的表:当地表(真实存放数据的表引擎),分布式表(署理了多个节点上的当地表,相称于"分库分表"的Proxy)。当ClickHouse的节点收到两表的Join关联分析时,题目比力收敛,无非是以下几种环境:当地表 Join 分布式表 、当地表 Join 当地表、 分布式表 Join 分布式表、分布式表 Join 当地表,这四种环境会怎样实行这里先放一下,等下一末节再先容。

接下来题目复杂化,怎样办理多个Join的关联查询?ClickHouse接纳递归子查询来办理这个题目,如下面的简朴例子所示ClickHouse会主动把多个Join的关联查询改写成子查询举行嵌套, 规则非常简朴:1)Join的左右表必须是当地表、分布式表大概子查询;2)倾向把Join的左侧酿成子查询;3)从末了一个Join开始递归改写成子查询;4)对Join order不做任何改动;5)可以主动根据where条件改写Cross Join到Inner Join。下面是两个详细的例子资助各人明白:

例1

select * from local_tabA join (select * from dist_tabB join local_tabC on dist_tabB.key2 = local_tabC.key2) as sub_Q1 on local_tabA.key1 = sub_Q1.key1 join dist_tabD on local_tabA.key1 = dist_tabD.key1; =============> select * from (select * from local_tabA join (select * from dist_tabB join local_tabC on dist_tabB.key2 = local_tabC.key2) as sub_Q1 on local_tabA.key1 = sub_Q1.key1) as sub_Q2 join dist_tabD on sub_Q2.key1 = dist_tabD.key1;

睁开全文

例2

select * from local_tabA join (select * from dist_tabB join local_tabC on dist_tabB.key2 = local_tabC.key2) as sub_Q1 on local_tabA.key1 = sub_Q1.key1 join dist_tabD on local_tabA.key1 = dist_tabD.key1; =============> select * from (select * from local_tabA join (select * from dist_tabB join local_tabC on dist_tabB.key2 = local_tabC.key2) as sub_Q1 on local_tabA.key1 = sub_Q1.key1) as sub_Q2 join dist_tabD on sub_Q2.key1 = dist_tabD.key1;

Join关联中的子查询在盘算引擎里就相干于是一个当地的"暂时表",只不外这个暂时表的Input Stream对接的是一个子查询的Output Stream。以是在处置惩罚多个Join的关联查询时,ClickHouse会把查询拆成递归的子查询,每一次递归只处置惩罚一个Join关联,单个Join关联中,左右表输入有大概是当地表、分布式表、子查询,如许题目就简化了。

这种简朴的递归子查询办理方案纯在最致命的缺陷是:

(1)体系没有主动优化本领,Join reorder是优化器的紧张课题,但是ClickHouse完全不提供这个本领,对内核不敷相识的用户根本无法写出性能最佳的关联查询,但是对履历老道的工程师来说这是另一种体验:可以完全掌控SQL的实行筹划。

(2)无法完全发挥分布式盘算的本领,ClickHouse在两表的Join关联中可否使用分布式算力举行join盘算取决于左表是否是分布式表,只有当左表是分布式表时才有大概使用上Cluster的盘算本领,也就是左表是当地表大概子查询时Join盘算过程只在一个节点举行。

(3)多个大表的Join关联轻易引起节点的OOM,ClickHouse中的Hash Join算子现在不支持spill(落盘),递归子查询必要节点在内存中同时维护多个完备的Hash Table来完成末了的Join关联。

两表Join规则

上一节先容了ClickHouse怎样使用递归子查询来办理多个Join的关联分析,终极体系只会focus在单个Join的关联分析上。除了通例的Join方式修饰词以外,ClickHouse还引入了别的一个Join流程修饰词"Global",它会影响整个Join的实行筹划。节点真正接纳Global Join举行关联的条件条件是左表必须是分布式表,Global Join会构建一个内存暂时表来生存Join右测的数据,然后把左表的Join盘算使命分发给全部署理的存储节点,收到Join盘算使命的存储节点会跨节点拷贝内存暂时表的数据,用以构建Hash Table。

下面依次先容全部大概出现的单个Join关联分析场景:

(1)(当地表/子查询)Join(当地表/子查询):通例当地Join,Global Join不见效

(2)(当地表/子查询)Join(分布式表):分布式表数据全部读到当前节点举行Hash Table构建,Global Join不见效

(3)(分布式表)Join(当地表/子查询):Join盘算使命分发到分布式表的全部存储节点上,存储节点上收到的Join右表取决于是否接纳Global Join计谋,假如不是Global Join则把右测的(当地表名/子查询)直接转给全部存储节点。假如是Global Join则当前节点会构建Join右测数据的内存表,收到Join盘算使命的节点会来拉取这个内存表数据。

(4)(分布式表)Join(分布式表):Join盘算使命分发到分布式表的全部存储节点上,存储节点上收到的Join右表取决于是否接纳Global Join计谋,假如不是Global Join则把右测的分布式表名直接转给全部存储节点。假如是Global Join则当前节点会把右测分布式表的数据全部网络起来构建内存表,收到Join盘算使命的节点会来拉取这个内存表数据。

从上面可以看出只有分布式表的Join关联是可以举行分布式盘算的,Global Join可以提前盘算Join右测的效果数据构建内存表,当Join右测是带过滤条件的分布式表大概子查询时,低落了Join右测数据重复盘算的次数,另有一种场景是Join右表只在当前节点存在则此时必须利用Global Join把它更换成内存暂时表,由于直接把右表名转给其他节点肯定会报错。

ClickHouse中另有一个开关和Join关联分析的举动有关:distributed_product_mode,它只是一个简朴的查询改写Rule用来改写两个分布式表的Join举动。当set distributed_product_mode = 'LOCAL'时,它会把右表改写成署理的存储表名,这要求左右表的数据分区对齐,否则Join效果就堕落了,当set distributed_product_mode = 'GLOBAL'时,它会把主动改写Join到Global Join。但是这个改写Rule只针对左右表都是分布式表的case,复杂的多表关联分析场景下对SQL的优化作用比力小,照旧不要去依靠这个主动改写的本领。

ClickHouse的分布式Join关联分析中另有别的一个特点是它并不会对左表的数据举行re-sharding,每一个收到Join使命的节点都会要全量的右表数据来构建Hash Table。在一些场景下,假如用户确定Join左右表的数据是都是按照某个Join key分区的,则可以利用(分布式表)Join(当地表)的方式来缓解一下这个题目。但是ClickHouse的分布式表Sharding计划并不包管Cluster在调解节点后数据能完全分区对齐,这是用户必要留意的。

小结

总结一下上面两节的分析,ClickHouse当前的MPP盘算模子并不善于做多表关联分析,重要存在的题目:1)节点间数据shuffle膨胀,Join关联时没有数据re-sharding本领,每个盘算节点都必要shuffle全量右表数据;2)Join内存膨胀,缘故原由同上;3)非Global Join下大概引起盘算风暴,盘算节点重复实行子查询;4)没有Join reorder优化。此中的1和3还会随着节点数目增长变得更加显着。在多表关联分析的场景下,用户应该尽大概为小表构建Dictionary,并利用dictGet内置函数来取代Join,针对无法制止的多表关联分析应该直接写成嵌套子查询的方式,并根据真实的查询实行环境实验调解Join order探求最优的实行筹划。当前ClickHouse的MPP盘算模子下,仍旧存在不少查询优化的小"bug"大概导致性能不如预期,比方列裁剪没有下推,过滤条件没有下推,partial agg没有下推等等,不外这些小题目都是可以修复。

资源隔离近况

当前的ClickHouse开源版本在体系的资源管理方面已经做了许多的feature,我把它们总结为三个方面:全链路(线程-》查询-》用户)的资源利用追踪、查询&用户级别资源隔离、资源利用限流。对于ClickHouse的资深DBA来说,这些资源追踪、隔离、限流功能已经可以办理非常多的题目。接下来我将睁开先容一下ClickHouse在这三个方面的功能计划实现。

trace & profile

ClickHouse的资源利用都是从查询thread级别就开始举行追踪,重要的相干代码在 ThreadStatus 类中。每个查询线程都会有一个thread local的ThreadStatus对象,ThreadStatus对象中包罗了对内存利用追踪的 MemoryTracker、profile cpu time的埋点对象 ProfileEvents、以及监控thread 热门线程栈的 QueryProfiler。

1.MemoryTracker

ClickHouse中有许多差别level的MemoryTracker,包罗线程级别、查询级别、用户级别、server级别,这些MemoryTracker会通过parent指针构造成一个树形布局,把内存申请开释信息层层反馈上去。

MemoryTrack中另有额外的峰值信息(peak)统计,内存上限查抄,一旦某个查询线程的申请内存哀求在上层(查询级别、用户级别、server级别)MemoryTracker碰到凌驾限定错误,查询线程就会抛出OOM非常导致查询退出。同时查询线程的MemoryTracker每申请肯定量的内存都会统计出当前的工作栈,非常方便排查内存OOM的缘故原由。

ClickHouse的MPP盘算引擎中每个查询的主线程都会有一个ThreadGroup对象,每个MPP引擎worker线程在启动时必须要attach到ThreadGroup上,在线程退出时detach,这包管了整个资源追踪链路的完备通报。末了一个题目是怎样把CurrentThread::MemoryTracker hook到体系的内存申请开释上去?ClickHouse起首是重载了c++的new_delete operator,其次针对必要利用malloc的一些场景封装了特别的Allocator同步内存申请开释。为了办理内存追踪的性能题目,每个线程的内存申请开释会在thread local变量上举行积攒,末了以大块内存的情势同步给MemoryTracker。

class MemoryTracker { std::atomic<Int64> amount {0}; std::atomic<Int64> peak {0}; std::atomic<Int64> hard_limit {0}; std::atomic<Int64> profiler_limit {0}; Int64 profiler_step = 0; /// Singly-linked list. All information will be passed to subsequent memory trackers also (it allows to implement trackers hierarchy). /// In terms of tree nodes it is the list of parents. Lifetime of these trackers should "include" lifetime of current tracker. std::atomic<MemoryTracker *> parent {}; /// You could specify custom metric to track memory usage. CurrentMetrics::Metric metric = CurrentMetrics::end(); ... }

2.ProfileEvents:

ProfileEvents顾名思义,是监控体系的profile信息,覆盖的信息非常广,全部信息都是通过代码埋点举行网络统计。它的追踪链路和MemoryTracker一样,也是通过树状布局构造层层追踪。此中和cpu time相干的焦点指标包罗以下:

///Total (wall clock) time spent in processing thread. RealTimeMicroseconds; ///Total time spent in processing thread executing CPU instructions in user space. ///This include time CPU pipeline was stalled due to cache misses, branch mispredictions, hyper-threading, etc. UserTimeMicroseconds; ///Total time spent in processing thread executing CPU instructions in OS kernel space. ///This include time CPU pipeline was stalled due to cache misses, branch mispredictions, hyper-threading, etc. SystemTimeMicroseconds; SoftPageFaults; HardPageFaults; ///Total time a thread spent waiting for a result of IO operation, from the OS point of view. ///This is real IO that doesn't include page cache. OSIOWaitMicroseconds; ///Total time a thread was ready for execution but waiting to be scheduled by OS, from the OS point of view. OSCPUWaitMicroseconds; ///CPU time spent seen by OS. Does not include involuntary waits due to virtualization. OSCPUVirtualTimeMicroseconds; ///Number of bytes read from disks or block devices. ///Doesn't include bytes read from page cache. May include excessive data due to block size, readahead, etc. OSReadBytes; ///Number of bytes written to disks or block devices. ///Doesn't include bytes that are in page cache dirty pages. May not include data that was written by OS asynchronously OSWriteBytes; ///Number of bytes read from filesystem, including page cache OSReadChars; ///Number of bytes written to filesystem, including page cache OSWriteChars;

以上这些信息都是从linux体系中直接收罗,参考 sys/resource.h 和 linux/taskstats.h。收罗没有固定的频率,体系在查询盘算的过程中每处置惩罚完一个Block的数据就会依据间隔前次收罗的时间隔断决定是否收罗最新数据。

3.QueryProfiler:

QueryProfiler的焦点功能是抓取查询线程的热门栈,ClickHouse通过对线程设置timer_create和自界说的signal_handler让worker线程定时收到SIGUSR信号量记载本身当前所处的栈,这种方法是可以抓到全部被lock block大概sleep的线程栈的。

除了以上三种线程级别的trace&profile机制,ClickHouse另有一套server级别的Metrics统计,也是通过代码埋点记载体系中全部Metrics的瞬时值。ClickHouse底层的这套trace&profile本领保障了用户可以很方便地从体系硬件层面去定位查询的性能瓶颈点大概OOM缘故原由,全部的metrics, trace, profile信息都有对象的system_log体系表可以追溯汗青。

资源隔离

资源隔离必要关注的点包罗内存、CPU、IO,现在ClickHouse在这三个方面都做了差别水平功能:

1.内存隔离

当前用户可以通过max_memory_usage(查询内存限定),max_memory_usage_for_user(用户的内存限定),max_memory_usage_for_all_queries(server的内存限定),max_concurrent_queries_for_user(用户并发限定),max_concurrent_queries(server并发限定)这一套参数去规划体系的内存资源利用做到用户级别的隔离。但是当用户举行多表关联分析时,体系派发的子查询会突破用户的资源规划,全部的子查询都属于default用户,大概引起用户查询的内存超用。

2.CPU隔离

ClickHouse提供了Query级别的CPU优先级设置,固然也可以为差别用户的查询设置差别的优先级,有以下两种优先级参数:

///Priority of the query. ///1 - higher value - lower priority; 0 - do not use priorities. ///Allows to freeze query execution if at least one query of higher priority is executed. priority; ///If non zero - set corresponding 'nice' value for query processing threads. ///Can be used to adjust query priority for OS scheduler. os_thread_priority;

3.IO隔离

ClickHouse现在在IO上没有做任何隔离限定,但是针对异步merge和查询都做了各自的IO限定,只管制止IO打满。随着异步merge task数目增多,体系会开始限定后续单个merge task涉及到的Data Parts的disk size。在查询并行读取MergeTree data的时间,体系也会统计每个线程当前的IO吞吐,假如吞吐不达标则会反压读取线程,低落读取线程数缓解体系的IO压力,以上这些限定步伐都是从局部来缓解题目的一个本领。

Quota限流

除了静态的资源隔离限定,ClickHouse内部另有一套时序资源利用限流机制--Quota。用户可以根据查询的用户大概Client IP对查询举行分组限流。限流和资源隔离差别,它是束缚查询实行的"速率",当前重要包罗以下几种"速率":

QUERIES; /// Number of queries. ERRORS; /// Number of queries with exceptions. RESULT_ROWS; /// Number of rows returned as result. RESULT_BYTES; /// Number of bytes returned as result. READ_ROWS; /// Number of rows read from tables. READ_BYTES; /// Number of bytes read from tables. EXECUTION_TIME; /// Total amount of query execution time in nanoseconds.

用户可以自界说规划本身的限流计谋,防止体系的负载(IO、网络、CPU)被打爆,Quota限流可以以为是体系自我掩护的本领。体系会根据查询的用户名、IP地点大概Quota Key Hint来为查询绑定对应的限流计谋。盘算引擎在算子之间通报Block时会查抄当前Quota组内的流速是否过载,进而通过sleep查询线程来低落体系负载。

小结

总结一下ClickHouse在资源隔离/trace层面的优缺点:ClickHouse为用户提供了非常多的工具组件,但是短缺团体性的办理方案。以trace & profile为例,ClickHouse在自身体系里集成了非常美满的trace / profile / metrics日记和瞬时状态体系表,在排查性能题目的过程中它的链路是完备的。但题目是这个链路太复杂了,对一样平常用户来说排查非常困难,尤其是碰上递归子查询的多表关联分析时,必要从用户查询到一层子查询到二层子查询步步深入分析。当前的资源隔离方案出现给用户的更加是一堆设置,根本不是一个完备的功能。Quota限流固然是一个完备的功能,但是却不轻易利用,由于用户不知道怎样量化公道的"速率"。

弹性资源队列

第一章为各人先容了ClickHouse的MPP盘算模子,焦点想论述的点是ClickHouse这种简朴的递归子查询盘算模子在资源使用上黑白常粗暴的,假如没有很好的资源隔离和体系过载掩护,节点很轻易就会由于bad sql变得不稳固。第二章先容ClickHouse当前的资源利用trace profile功能、资源隔离功能、Quota过载掩护。但是ClickHouse现在在这三个方面做得都不敷完善,还必要深度打磨来提拔体系的稳固性和资源使用率。我以为重要从三个方面举行增强:性能诊断链路主动化利用户可以一键诊断,资源队列功能增强,Quota(负载限流)做成主动化并拉通来看查询、写入、异步merge使命对体系的负载,防止过载。

阿里云数据库ClickHouse在ClickHouse开源版本上即将推出用户自界说的弹性资源队列功能,资源队列DDL界说如下:

CREATE RESOURCE QUEUE [IF NOT EXISTS | OR REPLACE] test_queue [ON CLUSTER cluster] memory=10240000000, ///资源队列的总内存限定 concurrency=8, ///资源队列的查询并发控制 isolate=0, ///资源队列的内存抢占隔离级别 priority=high ///资源队列的cpu优先级和内存抢占优先级 TO {role [,...] | ALL | ALL EXCEPT role [,...]};

我以为资源队列的焦点题目是要在保障用户查询稳固性的底子上最大化体系的资源使用率和查询吞吐。传统的MPP数据库雷同GreenPlum的资源队列计划头脑是队列之间的内存资源完全隔离,通过优化器去评估每一个查询的复杂度加上队列的默人并发度来决定查询在队列中可占用的内存巨细,在查询真实开始实行之前已经限定了它可利用的内存,加上GreenPlum强盛的盘算引擎全部算子都可以落盘,使得资源队列可以保障体系内的查询稳固运行,但是吞吐并不肯定是最大化的。由于GreenPlum资源队列之间的内存不是弹性的,有队列空闲下来它的内存资源也不能给其他队列利用。抛开资源队列间的弹性题目,其要想做到单个资源队列内的查询稳固高效运行离不开Greenplum的两个焦点本领:CBO优化器智能评估出查询必要占用的内存,全算子可落盘的盘算引擎。

ClickHouse现在的近况是:1)没有优化器资助评估查询的复杂度,2)整个盘算引擎的落盘本领比力弱,在限定内存的环境下无法保障query顺遂实行。因此我们联合ClickHouse盘算引擎的特色,计划了一套弹性资源队列模子,此中焦点的弹性内存抢占原则包罗以下几个:

ClickHouse弹性资源队列的计划原则就是答应内存资源抢占来到达资源使用率的最大化,同时动态调解资源队列的并发限定来防止bad query出现时导致用户的查询大面积失败。由于盘算引擎的束缚限定,现在无法保障查询完全没有OOM,但是用户端可以通不对误信息来判定查询是否属于bad sql,同时对误杀的查询举行retry。

作者:仁劼

本文为阿里云原创内容,未经答应不得转载返回搜狐,检察更多

责任编辑:





上一篇:特朗普照旧签了所谓“台湾包管法”,鼓吹对台军售常态化 ...
下一篇:三星手机新专利:隐蔽式前置摄像头,且支持SPen
您需要登录后才可以回帖 登录 | 加入社区

本版积分规则

 

QQ|申请友链|小黑屋|手机版|Hlshell Inc. ( 豫ICP备16002110号-5 )

GMT+8, 2024-5-17 19:44 , Processed in 0.187177 second(s), 44 queries .

HLShell有权修改版权声明内容,如有任何爭議,HLShell將保留最終決定權!

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表