大數(shù)據(jù)丨ClickHouse在京東能源管理平臺(tái)的實(shí)踐

ClickHouse是一款面向大數(shù)據(jù)場(chǎng)景下的OLAP數(shù)據(jù)庫(kù),相比于傳統(tǒng)的基于Hadoop生態(tài)圈的OLAP大數(shù)據(jù)分析系統(tǒng),ClickHouse具有極致的查詢性能、輕量級(jí)的架構(gòu)設(shè)計(jì)及維護(hù)簡(jiǎn)單等優(yōu)勢(shì)。目前社區(qū)活躍度高,業(yè)界應(yīng)用實(shí)踐日趨廣泛。
京東能源管理平臺(tái)是京東科技IoT產(chǎn)品部面向政企客戶推出的一款利用物聯(lián)網(wǎng)、大數(shù)據(jù)和AI技術(shù)實(shí)現(xiàn)用能企事業(yè)單位對(duì)能源大數(shù)據(jù)進(jìn)行采集、監(jiān)測(cè)、分析和告警的能耗分析產(chǎn)品,旨在幫助客戶實(shí)現(xiàn)節(jié)能減排,降低單位產(chǎn)品能耗。

能源指標(biāo)包括用電量、用水量和用天然氣量,維度有時(shí)間維度(年、月、周、日、時(shí))、廠家、車間、生產(chǎn)線類型、生產(chǎn)線、設(shè)備。針對(duì)這些指標(biāo)和維度,提供了實(shí)時(shí)的數(shù)據(jù)多維分析與診斷服務(wù)。
對(duì)于數(shù)據(jù)指標(biāo)的多維度分析場(chǎng)景,上世紀(jì)業(yè)界就提出了BI(商業(yè)智能)的概念。相較于OLTP(聯(lián)機(jī)事務(wù))系統(tǒng),業(yè)界把此類面向BI的系統(tǒng)統(tǒng)稱為OLAP(聯(lián)機(jī)分析)系統(tǒng)。伴隨著計(jì)算機(jī)軟件技術(shù)的發(fā)展、從單機(jī)工具的少量數(shù)據(jù)分析(如Excel),到中等規(guī)模數(shù)據(jù)通過(guò)分析型關(guān)系數(shù)據(jù)庫(kù)構(gòu)建(如微軟的SSAS)的OLAP,再到今日的大數(shù)據(jù)時(shí)代,海量數(shù)據(jù)的實(shí)時(shí)OLAP分析引擎,技術(shù)上的推陳出新,工具系統(tǒng)上百花齊放百家爭(zhēng)鳴,各有優(yōu)勢(shì),但大體上可以將它們從架構(gòu)模式上劃分為兩大類:
1. MPP架構(gòu)。MPP架構(gòu)特點(diǎn)是服務(wù)將接收到的查詢請(qǐng)求發(fā)送到每個(gè)計(jì)算節(jié)點(diǎn),待計(jì)算節(jié)點(diǎn)計(jì)算完成后,通過(guò)一個(gè)節(jié)點(diǎn)將最終結(jié)果匯總在一起得到最終結(jié)果。典型實(shí)現(xiàn)如Presto、Impala、SparkSQL、Drill等。MPP架構(gòu)的特點(diǎn)是支持靈活的數(shù)據(jù)模型,要達(dá)到較高性能對(duì)內(nèi)存開(kāi)銷大。
2. 預(yù)計(jì)算系統(tǒng)。預(yù)計(jì)算的核心思想是利用空間換時(shí)間,通過(guò)深入業(yè)務(wù)理解,將需要查詢的數(shù)據(jù)指標(biāo)和維度組合進(jìn)行預(yù)處理,將計(jì)算好的結(jié)果存入數(shù)據(jù)庫(kù)并建立對(duì)應(yīng)索引,實(shí)現(xiàn)查詢加速。典型實(shí)現(xiàn)如Kylin、Druid。預(yù)計(jì)算系統(tǒng)特點(diǎn)是性能較高,但靈活性較差,一般對(duì)數(shù)據(jù)模型調(diào)整會(huì)涉及到歷史數(shù)據(jù)的重跑,維護(hù)困難。

從上表可知,目前業(yè)界還沒(méi)有一個(gè)OLAP引擎能夠同時(shí)兼顧性能和靈活性的要求,京東能源管理平臺(tái)在做技術(shù)選型的時(shí)候,綜合考慮了模型的靈活性、部署的難易程度、開(kāi)發(fā)成本、可維護(hù)性以及是否適合云端部署等因素,最終決定使用基于MPP架構(gòu)的ClickHouse作為我們的OLAP引擎。
京東能源管理平臺(tái)主要是對(duì)各種表計(jì)(水表、電表、天然氣表等)設(shè)備上報(bào)的計(jì)數(shù)進(jìn)行多維度分析統(tǒng)計(jì)、AI診斷和出具能耗報(bào)表等。表計(jì)的原始數(shù)據(jù)通常都是累計(jì)值,如電量度數(shù)就是一個(gè)從電表安裝以來(lái),所有耗電量的一個(gè)累計(jì)。因此,我們?cè)跀?shù)據(jù)接入前會(huì)引入一個(gè)差分器對(duì)數(shù)據(jù)進(jìn)行預(yù)處理,使得進(jìn)入ClickHouse的指標(biāo)數(shù)據(jù)變成可直接累加的指標(biāo),方便利用SQL對(duì)接ClickHouse實(shí)現(xiàn)多維的查詢服務(wù)。架構(gòu)圖如下:

說(shuō)明:
物管平臺(tái):對(duì)設(shè)備的管理,管理物模型及設(shè)備狀態(tài)、采集設(shè)備數(shù)據(jù)。
消息總線:kafka消息隊(duì)列,利用JSON格式數(shù)據(jù)實(shí)現(xiàn)物管平臺(tái)和能平臺(tái)的數(shù)據(jù)交互。
差分器:對(duì)每次上報(bào)的累計(jì)值同上一次上報(bào)的累計(jì)值做差值計(jì)算,得到可累加指標(biāo)。
異常規(guī)則鏈:提供一個(gè)異常規(guī)則集,用于差分器判定上報(bào)數(shù)據(jù)是否異常,如異常則進(jìn)行記錄,數(shù)據(jù)不作處理。
OLAP引擎:基于ClickHouse實(shí)現(xiàn)的OLAP引擎。
多維分析服務(wù):提供通用的數(shù)據(jù)多維分析查詢服務(wù),能夠通過(guò)統(tǒng)一的API實(shí)現(xiàn)各種維度和指標(biāo)的組合查詢。
政府和企業(yè)界面:政企客戶的WEB界面。
通過(guò)上面的架構(gòu)圖可以看出,能源平臺(tái)采用ClickHouse作為OLAP引擎提供多維查詢服務(wù)。下面重點(diǎn)從數(shù)據(jù)的接入、存儲(chǔ)以及通用化接口設(shè)計(jì)方面談一談
ClickHouse的應(yīng)用:
數(shù)據(jù)接入
ClickHouse基于kafka引擎表的數(shù)據(jù)接入可以看做是一個(gè)典型的ETL過(guò)程,數(shù)據(jù)的抽取(Extract)是通過(guò)建立一張kafka引擎表,產(chǎn)生消費(fèi)端訂閱kafka topic實(shí)現(xiàn);數(shù)據(jù)的轉(zhuǎn)換(Transform)通過(guò)物化視圖實(shí)現(xiàn);數(shù)據(jù)最終加載(Load)進(jìn)MergeTree表,實(shí)現(xiàn)實(shí)際數(shù)據(jù)存儲(chǔ)。

創(chuàng)建Kafka表示例:
1CREATE?TABLE?statistics_kafka?ON?CLUSTER?'{cluster}'?(
2??timestamp?UInt64,
3??level?String,
4??message?String
5?)?ENGINE?=?Kafka?SETTINGS?kafka_broker_list?=?'kafka.jd.com:9092',
6?????????????????????????kafka_topic_list?=?'statistics',
7?????????????????????????kafka_group_name?=?'gp-st',
8?????????????????????????kafka_format?=?'JSONEachRow',
9?????????????????????????kafka_skip_broken_messages?=?1,?
10?????????????????????????kafka_num_consumers?=?3;
<左右滑動(dòng)以查看完整代碼>
kafka_broker_list: kafka broker地址。
kafka_topic_list:消費(fèi)的topic。
kafka_group_name:消費(fèi)groupId。
kafka_format:數(shù)據(jù)格式JSONEachRow表示消息體為JSON格式。
kafka_skip_broken_messages:表示忽略的kafka異常消息條數(shù),默認(rèn)為0。
kafka_num_consumers:消費(fèi)者個(gè)數(shù),默認(rèn)值為1,建議同kafka分區(qū)數(shù)對(duì)應(yīng)。
創(chuàng)建物化視圖示例:
1CREATE?MATERIALIZED?VIEW?statistics_view?ON?CLUSTER?'{cluster}'?TO?statistics_replica?AS
2SELECT?timestamp,
3???????level,
4???????message
5FROM?statistics_kafka;<左右滑動(dòng)以查看完整代碼>
創(chuàng)建MergeTree引擎表示例:
1CREATE?TABLE?statistics_replica?ON?CLUSTER?'{cluster}'{
2 timestamp?UInt64,
3 dt?String,
4 deviceId?String,
5 level?String,
6 message?String
7}?ENGINE?=?ReplicatedMergeTree('/clickhouse/tables/{shard}/statistics_replica','{replica}')
8PARTITION?BY?dt
9ORDER?BY?(dt,deviceId,level);<左右滑動(dòng)以查看完整代碼>
存儲(chǔ)
ClickHouse表類型
本地表:實(shí)際數(shù)據(jù)存儲(chǔ)的表,如上示例表statistics_replica。
分布式表:一個(gè)邏輯上的表, 可以理解為數(shù)據(jù)庫(kù)中的視圖, 一般查詢都查詢分布式表. 分布式表引擎會(huì)將我們的查詢請(qǐng)求路由本地表進(jìn)行查詢, 然后進(jìn)行匯總最終返回給用戶。創(chuàng)建分布式表示例:
1CREATE?TABLE?statistics?ON?CLUSTER?'{cluster}'?AS?statistics_replica
2ENGINE?=?Distributed(ck_cluster_1,test,events_local,rand());<左右滑動(dòng)以查看完整代碼>
Replication和Sharding
Replication是ClickHouse提供的副本機(jī)制,對(duì)于Replicated MergeTree 系列復(fù)制表,可以設(shè)置每個(gè)表有多份完全一樣的數(shù)據(jù)存放在不同的計(jì)算節(jié)點(diǎn)上,每一份數(shù)據(jù)都是完整的,并且稱為一個(gè)副本。
Shard:將表中的數(shù)據(jù)按照一定的規(guī)則拆分為多個(gè)部分,每個(gè)部分的數(shù)據(jù)均存儲(chǔ)在不同的計(jì)算節(jié)點(diǎn)上,每個(gè)計(jì)算節(jié)點(diǎn)上的數(shù)據(jù)稱為一個(gè)分片。

ClickHouse基于Replicated MergeTree引擎與Zookeeper實(shí)現(xiàn)了復(fù)制表機(jī)制,在創(chuàng)建表時(shí),可以決定表是否高可用。上一節(jié)的statistics_replica表,其中/clickhouse/tables/{shard}/statistics_replica表示Zookeeper中對(duì)應(yīng)副本表的node。當(dāng)數(shù)據(jù)寫入ReplicatedMergeTree表時(shí),過(guò)程如下:

某一個(gè)ClickHouse節(jié)點(diǎn)接收到數(shù)據(jù)寫入請(qǐng)求。
通過(guò)interserver HTTP port端口同步到其他實(shí)例。
更新Zookeeper集群上的node信息。

ClickHouse提供標(biāo)準(zhǔn)的SQL查詢引擎,通過(guò)JDBC引用程序可以實(shí)現(xiàn)多ClickHouse的基本操作。OLAP的常規(guī)操作如上卷、下鉆和切片會(huì)涉及到多種維度自由組合、多種指標(biāo)交叉剖析的過(guò)程,如果服務(wù)端采用Mybatis或JPA等常規(guī)ORM操作,工程師很容易根據(jù)不同的查詢場(chǎng)景要求設(shè)計(jì)出對(duì)應(yīng)的接口,亦或是根據(jù)大量的分支操作設(shè)計(jì)出復(fù)雜的判定性接口,鑒于此,作者從mdx思想獲得啟示,設(shè)計(jì)一套對(duì)OLAP優(yōu)化的通用多維服務(wù)查詢接口。
首先,一個(gè)典型的分析類SQL語(yǔ)句如下:
1SELECT?day_str,
2???????factory_name,
3???????workshop_name,
4???????prodline_name,
5???????device_id,
6???????SUM(w_total)?AS?total
7FROM?statistics
8WHERE?day_str?BETWEEN?'2020-10-01'?AND?'2020-12-31'
9GROUP?BY?day_str,factory_name,workshop_name,prodline_name,device_id
10ORDER?BY?day_str?ASC;
<左右滑動(dòng)以查看完整代碼>
如上語(yǔ)句,我們翻譯成業(yè)務(wù)語(yǔ)言為『分別查詢2020年4季度全廠所有設(shè)備的耗電量』,從這里我們可以清楚的知道這里的維度是指『設(shè)備名稱』,指標(biāo)為『耗電量』,基于此,可以進(jìn)一步歸類,維度通常出現(xiàn)在SQL語(yǔ)句的SELECT、WHERE、GROUP BY和ORDER BY后面,指標(biāo)則通常出現(xiàn)在SELECT后面,也就是可以總結(jié)如下模式:
1SELECT?{維度},{指標(biāo)}
2FROM?table_name
3WHERE?{維度}='xxx'
4GROUP?BY?{維度}
5ORDER?BY?{維度};
<左右滑動(dòng)以查看完整代碼>
因此,我們可以設(shè)計(jì)如下通用接口方法:
1//通用方法
2List<Map<String,Object>>?queryStatisticsResult(Query?query);
3
4//Query類
5public?class?Query?{
6???? private?static?final?long?serialVersionUID?=?4904019884726531900L;
7???? /**
8????? *?維度
9????? */
10????private?List<String>?dimensions;
11????/**
12?????*?指標(biāo)
13?????*/
14????private?List<Measure>?measures;
15????/**
16?????*?過(guò)濾條件
17?????*/
18????private?List<Filter>?where;
19}
20
21//Measure類
22public?class?Measure?implements?Serializable?{
23
24????private?static?final?long?serialVersionUID?=?-8556179136317748835L;
25????/**
26?????*?指標(biāo)名稱
27?????*/
28????@NonNull
29????private?String?name;
30????/**
31?????*?列名
32?????*/
33????@NonNull
34????private?String?field;
35????/**
36?????*?聚合類型
37?????*/
38????@NonNull
39????private?AggregationEnum?expression;
40}
41
42//聚合枚舉
43public?enum?AggregationEnum?{
44????SUM,AVG,COUNT,MIN,MAX,COUNT_DISTINCT,PERCENTILE;
45}
<左右滑動(dòng)以查看完整代碼>

本文重點(diǎn)介紹了京東綜合能源管理平臺(tái)多維數(shù)據(jù)分析引擎的架構(gòu)和設(shè)計(jì),從數(shù)據(jù)接入、存儲(chǔ)和多維分析服務(wù)設(shè)計(jì)的角度,闡述了ClickHouse的一種典型應(yīng)用場(chǎng)景。希望通過(guò)本文讓讀者在應(yīng)對(duì)大數(shù)據(jù)實(shí)時(shí)OLAP領(lǐng)域,提供一種思路和方法。當(dāng)然,限于篇幅和本人水平有限,沒(méi)有進(jìn)一步展開(kāi)闡述更多的可能性方案,隨著我們對(duì)于業(yè)務(wù)的深入,系統(tǒng)的迭代升級(jí),適宜于將來(lái)更優(yōu)方案勢(shì)必會(huì)步步推出,也請(qǐng)期待。










