OLAP引擎這么多,為什么蘇寧選擇用Druid?
原創(chuàng)【51CTO.com原創(chuàng)稿件】隨著公司業(yè)務(wù)增長迅速,數(shù)據(jù)量越來越大,數(shù)據(jù)的種類也越來越豐富,分析人員對數(shù)據(jù)處理的響應(yīng)延時要求也越來越高,傳統(tǒng)的大數(shù)據(jù)處理工具已經(jīng)無法滿足業(yè)務(wù)的需求。
特別是 OLAP 分析場景,需要對各種維度和度量進(jìn)行上卷、下鉆、切片和切塊分析,并要求分析結(jié)果能夠?qū)崟r返回。
因此我們調(diào)研和對比了一些目前主流的 OLAP 分析工具,針對聚合計(jì)算的實(shí)時分析,我們引入了開源分析工具 Druid。
Druid 介紹
說起 Druid,大家首先想到的是阿里的 Druid 數(shù)據(jù)庫連接池,而本文介紹的 Druid 是一個在大數(shù)據(jù)場景下的解決方案,是需要在復(fù)雜的海量數(shù)據(jù)下進(jìn)行交互式實(shí)時數(shù)據(jù)展現(xiàn)的 BI/OLAP 工具。
它有三個特點(diǎn):
- 處理的數(shù)據(jù)量規(guī)模較大。
- 可以進(jìn)行數(shù)據(jù)的實(shí)時查詢展示。
- 它的查詢模式是交互式的,這也說明其查詢并發(fā)能力有限。
目前 Druid 廣泛應(yīng)用在國內(nèi)外各個公司,比如阿里,滴滴,知乎,360,eBay,Hulu 等。
Druid 之所以能夠在 OLAP 家族中占據(jù)一席之地,主要依賴其強(qiáng)大的 MPP 架構(gòu)設(shè)計(jì),關(guān)于它的架構(gòu),這里就不展開描述了,感興趣的同學(xué)可以登陸官網(wǎng) druid.io 進(jìn)行了解。
除了 MPP 架構(gòu)外,它還運(yùn)用到了四點(diǎn)重要的技術(shù),分別是:
- 預(yù)聚合
- 列式存儲
- 字典編碼
- 位圖索引
預(yù)聚合算是 Druid 的一個非常大的亮點(diǎn),通過預(yù)聚合可以減少數(shù)據(jù)的存儲以及避免查詢時很多不必要的計(jì)算。
由于 OLAP 的分析場景大多只關(guān)心某個列或者某幾個列的指標(biāo)計(jì)算,因此數(shù)據(jù)非常適合列式存儲。
在列式存儲的基礎(chǔ)之上,再加上字段編碼,能夠有效的提升數(shù)據(jù)的壓縮率,然后位圖索引讓很多查詢最終直接轉(zhuǎn)化成計(jì)算機(jī)層面的位計(jì)算,提升查詢效率。
Druid 既然是 OLAP 工具,那它和其他 OLAP 工具有哪些差異呢?
圖 1:OLAP 工具的對比
從上圖可以看出,Kylin 和 Druid 整體上相比較其他兩個還是很有優(yōu)勢的:
相比較 Kylin,Druid 沒有模型管理和 cube 管理的能力,Kylin 無法提供實(shí)時查詢。
相比較 ES,Druid 的優(yōu)勢在于聚合計(jì)算,ES 的優(yōu)勢在于查明細(xì),在蘇寧,對 Druid 的使用,一般應(yīng)用在需要對數(shù)據(jù)進(jìn)行實(shí)時聚合查詢的場景。
Druid 在蘇寧的應(yīng)用場景
蘇寧很多業(yè)務(wù)場景都使用到了 Druid,本文將列舉兩個例子,分別是門店 App 系統(tǒng)以及諸葛系統(tǒng)。
門店 App 系統(tǒng)
門店 App 系統(tǒng)是一款集數(shù)據(jù)服務(wù)、銷售開單、會員營銷、收發(fā)盤退、績效管理、V 購用戶溝通、學(xué)習(xí)中心等于一體的門店店員移動工作平臺,其銷售界面如下所示:
圖 2:銷售界面
圖 3:客流界面
門店 App 業(yè)務(wù)大致情況如下:
- 數(shù)據(jù)量:保存近幾年的數(shù)據(jù)。
- 數(shù)據(jù)接入方式:Kafka 實(shí)時數(shù)據(jù)接入,隔天離線數(shù)據(jù)覆蓋昨天數(shù)據(jù)。
- 查詢方式:實(shí)時查詢。
- 業(yè)務(wù)實(shí)現(xiàn):topN 實(shí)現(xiàn)銷售額曲線展示,groupby 分組樓層客流分布,timeserise 做天匯總。
諸葛報表系統(tǒng)
諸葛報表系統(tǒng)是蘇寧重要的系統(tǒng)之一,能夠幫助業(yè)務(wù)做出決策分析,減少手工分析成本,幫助提高銷售,該系統(tǒng)可以主動給業(yè)務(wù)發(fā)送銷售數(shù)據(jù),推動業(yè)務(wù)進(jìn)行銷售關(guān)注和分析。
圖 4:諸葛報表系統(tǒng)
諸葛業(yè)務(wù)大致情況如下:
- 數(shù)據(jù)量:保存近幾年數(shù)據(jù)。
- 數(shù)據(jù)接入方式:Kafka 實(shí)時數(shù)據(jù)接入。
- 查詢方式:實(shí)時查詢。
- 業(yè)務(wù)實(shí)現(xiàn):topN 實(shí)現(xiàn)銷售餅圖展示,groupby 分組實(shí)現(xiàn)大區(qū)銷售排名。
上文簡單介紹了一下什么是 Druid 以及 Druid 在蘇寧的兩個業(yè)務(wù)場景應(yīng)用,那 Druid 在蘇寧的平臺建設(shè)是怎樣的呢?
Druid 在蘇寧的平臺建設(shè)
圖 5:兩種架構(gòu)
Druid 的平臺建設(shè)在蘇寧主要有兩種:
- 通過 OCEP(提供負(fù)載均衡,查詢路由功能等),使用 Druid 原生的能力,滿足業(yè)務(wù)一系列的需求。
- 結(jié)合蘇寧的天工系統(tǒng)和百川系統(tǒng),Druid 作為 OLAP 引擎的底層加速系統(tǒng),提供統(tǒng)一報表的查詢能力。
目前,大部分的業(yè)務(wù)使用 Druid 的方式主要還是第一種,有少量的業(yè)務(wù)使用的是第二種方式,隨著第二種方式的逐漸成熟,后面大家的業(yè)務(wù)會逐漸從第一種方式遷移到第二種上去,實(shí)現(xiàn)資源統(tǒng)一。
基于 OCEP 的平臺架構(gòu)
圖 6:基于 OCEP 的平臺架構(gòu)
該平臺主要依賴 OCEP,對外提供一系列的 OLAP 查詢服務(wù),滿足集團(tuán)內(nèi)部各種業(yè)務(wù)的維度指標(biāo)分析需求:
- 通過 tranquility 實(shí)時消費(fèi)業(yè)務(wù)數(shù)據(jù),發(fā)送到 Druid 的 realtime peon,并進(jìn)行 handoff 持久化到 HDFS 上,由 coordinator 進(jìn)行加載到 historical 中,提供查詢服務(wù)。
- 通過蘇寧自研的 IDE 任務(wù)調(diào)度系統(tǒng),將 HDFS 上的離線數(shù)據(jù)(一般是數(shù)倉數(shù)據(jù))經(jīng)過 mapreduce 任務(wù)處理完寫入到 Druid 指定的 HDFS 路徑下,同樣由 coordinator 進(jìn)行加載到 historical 中,提供查詢服務(wù)。
- 最后通過 OCEP,將業(yè)務(wù)的查詢路由到各個 broker 上,broker 再分發(fā)給 historical,經(jīng)過 historical 計(jì)算后,再向上一層一層返回給業(yè)務(wù)。
基于 OLAP 引擎的平臺架構(gòu)
圖 7:基于 OLAP 引擎的平臺架構(gòu)
為保證數(shù)據(jù)的一致性和統(tǒng)一性,該平臺基于 OLAP 引擎,為集團(tuán)各個業(yè)務(wù)提供統(tǒng)一的維度指標(biāo)分析系統(tǒng):
- 百川系統(tǒng)通過 OLAP 引擎構(gòu)建模型,OLAP 引擎根據(jù)業(yè)務(wù)需求,將模型拆分成若干個 cube,存儲到底層的 Druid,Hive,PG 和 ES。我們稱這個過程為模型加速,另外,百川系統(tǒng)自身會構(gòu)建各種各樣的指標(biāo)。
- 業(yè)務(wù)方,比如天工,諸葛等系統(tǒng)通過百川提供的指標(biāo),選擇其中一個或多個進(jìn)行報表的構(gòu)建,其查詢請求會發(fā)送到百川系統(tǒng)。
- 百川系統(tǒng)構(gòu)造 SQL 語句,再把請求發(fā)送到 OLAP 引擎,OLAP 引擎通過底層的 Spark 平臺,解析 SQL 語句,將請求路由到 Druid,ES,Hive 和 PG,其中,時序化數(shù)據(jù)的聚合查詢,將路由到 Druid 平臺,最后查詢結(jié)果一層一層匯總到上層的業(yè)務(wù)系統(tǒng)。
- 整個系統(tǒng)的監(jiān)控,通過云跡系統(tǒng)、華佗系統(tǒng)等進(jìn)行監(jiān)控,將系統(tǒng)日志接入云跡,將系統(tǒng)的 metric 信息接入華佗。
隨著 Druid 平臺建設(shè)的不斷推進(jìn),使用 Druid 的業(yè)務(wù)也越來越多,在使用的過程中也會遇到各種各樣的問題,下文總結(jié)了蘇寧業(yè)務(wù)開發(fā)人員在使用 Druid 中遇到的一些問題,希望對正在閱讀本文的讀者有些幫助。
Druid 使用建議
本小節(jié)主要想結(jié)合實(shí)際問題,給大家提供一些 Druid 的使用建議,供大家參考。
①什么樣的業(yè)務(wù)適合用 Druid?
建議如下:
- 時序化數(shù)據(jù):Druid 可以理解為時序數(shù)據(jù)庫,所有的數(shù)據(jù)必須有時間字段。
- 實(shí)時數(shù)據(jù)接入可容忍丟數(shù)據(jù)(tranquility):目前 tranquility 有丟數(shù)據(jù)的風(fēng)險,所以建議實(shí)時和離線一起用,實(shí)時接當(dāng)天數(shù)據(jù),離線第二天把今天的數(shù)據(jù)全部覆蓋,保證數(shù)據(jù)完備性。
- OLAP 查詢而不是 OLTP 查詢:Druid 查詢并發(fā)有限,不適合 OLTP 查詢。
- 非精確的去重計(jì)算:目前 Druid 的去重都是非精確的。
- 無 Join 操作:Druid 適合處理星型模型的數(shù)據(jù),不支持關(guān)聯(lián)操作。
- 數(shù)據(jù)沒有 update 更新操作,只對 segment 粒度進(jìn)行覆蓋:由于時序化數(shù)據(jù)的特點(diǎn),Druid 不支持?jǐn)?shù)據(jù)的更新。
②如何設(shè)置合理的 Granularity?
圖 8:Granularity 設(shè)置
首先解釋下 segmentGranularity 和 queryGranularity,前者是 segment 的組成粒度,后者是 segment 的聚合粒度。
要求 queryGranularity 小于等于 segmentGranularity,然后在數(shù)據(jù)導(dǎo)入時,按照下面的規(guī)則進(jìn)行設(shè)置。
segmentGranularity(離線數(shù)據(jù)導(dǎo)入的設(shè)置):
- 導(dǎo)入的數(shù)據(jù)是天級別以內(nèi)的:“hour”或者“day”。
- 導(dǎo)入的數(shù)據(jù)是天級別以上的:“day”。
- 導(dǎo)入的數(shù)據(jù)是年級別以上的:“month”。
需要說明的是,這里我們僅僅是簡單的通過 intervals 進(jìn)行 segmentGranularity 的設(shè)置,更加合理的做法應(yīng)該是結(jié)合每個 segment 的大小以及查詢的復(fù)雜度進(jìn)行綜合衡量。
考慮到 tranquility 實(shí)時任務(wù)的特殊性和數(shù)據(jù)的安全性,我們建議實(shí)時數(shù)據(jù)導(dǎo)入時,segmentGranularity 設(shè)置成“hour”。
queryGranularity:根據(jù)業(yè)務(wù)查詢最小粒度和查詢復(fù)雜度來定,假設(shè)查詢只需要到小時粒度,則該參數(shù)設(shè)置為“hour”。
③需要去重的維度到底需不需要定義到維度列中?
圖 9:去重維度定義
如果去重的維度只需要去重計(jì)算,沒有其他的作用,譬如進(jìn)行過濾或者作為分組字段,我們建議不要添加到維度列中,因?yàn)椴惶砑拥脑挘@樣數(shù)據(jù)的預(yù)聚合效果更好。
④如何選擇查詢方式?
常用的三種查詢:
- select sum(A) from DS where time>? [timeseries]
- select sum(A) from DS where time>? group by B order by C limit 2 [topN]
- select sum(A) from DS where time>? group by B,C order by C limit 2[groupby]
沒有維度分組的場景使用 timeseries,單維度分組查詢的場景使用 topN,多維度分組查詢場景使用 groupby。
由于 groupby 并不會將 limit 下推(Druid 新版本進(jìn)行了優(yōu)化,雖然可以下推,但是對于指標(biāo)的排序是不準(zhǔn)確的),所以單維度的分組查詢,盡量用 topN 查詢。
我們做的工作
從 Druid 引入蘇寧之后,不久便承擔(dān)起了 OLAP 分析的重任,作為底層核心引擎支撐模型和指標(biāo)服務(wù),并為集團(tuán)各條業(yè)務(wù)線的 OLAP 分析服務(wù),在過去的時間里,我們做了很多工作,本文列舉一些進(jìn)行說明。
①OCEP(Druid 集群前置 proxy)
圖 10:OCEP(Druid 集群前置 proxy)
OCEP 是 Druid 集群一個前置 proxy,通過它來提供更加完備的 Druid 集群化和服務(wù)化能力,并解決當(dāng)前 Druid 服務(wù)存在的各種問題。
它提供的功能主要有:
- 訪問鑒權(quán)(針對每個 datasource 提供 token 訪問鑒權(quán),保證數(shù)據(jù)安全)。
- 訪問審計(jì)(對每個查詢都會生成唯一的 queryId,提供完整的請求來源)。
- 請求攔截(對非預(yù)期的訪問,制定攔截策略,細(xì)化到具體的 datasource 和查詢語句)。
- 請求路由(根據(jù)集群名稱和 datasource,將請求路由到指定的 Druid 集群,并根據(jù)后端 broker 的壓力,將請求負(fù)載均衡各個 broker 上)。
- 服務(wù)隔離(可設(shè)置策略,對于不同的 datasource 的請求,可路由到指定的 broker 上,實(shí)現(xiàn) broker 隔離)。
②Druid 查詢客戶端
官方提供的查詢方式是通過編寫 Json 文件,以 HTTP 的方式請求 Druid,然而這種方式的缺點(diǎn)也很明顯,首先 Json 內(nèi)容書寫繁瑣,格式極易寫錯,另外在 Java 開發(fā)時,出現(xiàn)問題不利于定位。
圖 11:Json 語句
于是我們封裝了一層 Java API,如下圖:
圖 12:Druid Java Client
③資源隔離
圖 13:資源隔離
不同業(yè)務(wù)的數(shù)據(jù)量有大小之分以及對服務(wù)穩(wěn)定性要求不一樣,我們通過以下三點(diǎn)實(shí)現(xiàn)業(yè)務(wù)層面的隔離:
- Historical 分組:集群設(shè)置不同的 tier,存儲不同的業(yè)務(wù)數(shù)據(jù)。
- Broker 隔離:通過 OCEP 設(shè)置 datasource 白名單,不同的 broker 只提供某個或某幾個 datasource 的查詢。
- 冷熱數(shù)據(jù)隔離:通過設(shè)置 datasource 的 rule,將冷熱數(shù)據(jù)分別存儲在不同的 tier 中。
- Druid 白名單控制。
集群穩(wěn)定性壓倒一切,防止控制以外的機(jī)器對集群進(jìn)行無效查詢和攻擊,我們通過增加一個 whitelist 的 extension,以模塊的方式在服務(wù)端進(jìn)行白名單的控制。
并且可以針對不同的服務(wù)進(jìn)行控制,將 whitelist 的配置文件寫在 Druid 的 metadata 的 config 表中,實(shí)現(xiàn)動態(tài)更新。
圖 14:白名單 extension
圖 15:Druid 白名單配置
④Druid 離線導(dǎo)入時對 intervals 的控制
有些離線導(dǎo)入的任務(wù),占用了 YARN 太多的資源,個別任務(wù)消耗了上千個或者上萬的 container 資源,分析發(fā)現(xiàn)是由于業(yè)務(wù)設(shè)置的 segmentGranularity 不合理,最終會導(dǎo)致 segment 過多,產(chǎn)生很多 HDFS 小文件。
于是我們在 overlord 服務(wù)端,增加參數(shù)“druid.indexer.intervals.maxLimit”,對離線任務(wù)進(jìn)行判斷。
如果 segmentGranularity 和 interval 設(shè)置的不合理,將禁止提交。譬如,segmentGranularity 設(shè)置的是小時,interval 設(shè)置的間隔是 1 年,這種是不合理的,服務(wù)端將禁止數(shù)據(jù)導(dǎo)入。
圖 16:離線導(dǎo)入對 intervals 的控制參數(shù)配置
⑤Coordinator 自動 merge segment 時啟動 task 的并發(fā)數(shù)控制
在集群中,我們打開了 coordinator 自動 merge segment 的功能,coordinator 默認(rèn)每隔 30 分鐘,啟動 merge 線程,掃描所有的 datasource,將過小的 segment 按要求進(jìn)行合并。
每當(dāng)一批 segment 符合 merge 要求了,就會請求 overlord 進(jìn)行啟動 merge task。
如果集群內(nèi)小 segment 很多,merge task 將啟動無數(shù)個,堵塞 middleManager 的 peon 資源,我們增加限制 merge task 的并發(fā)數(shù)的參數(shù),保證每次 merge 線程只啟動一定數(shù)量的 task。
圖 17:設(shè)置 merge task 的并發(fā)數(shù)
⑥D(zhuǎn)ruid 監(jiān)控
監(jiān)控對于任何一個系統(tǒng)而言都是非常重要的,可以幫助我們提前預(yù)知系統(tǒng)的健康狀況,Druid 的監(jiān)控主要有兩點(diǎn),業(yè)務(wù)查詢情況和平臺運(yùn)行情況。
前者主要包括 datasource 的查詢量、查詢耗時、網(wǎng)絡(luò)流量等;后者主要包括各個服務(wù)的 gc 情況、cpu 和內(nèi)存使用情況、空閑 Jetty 線程數(shù)等。
我們的監(jiān)控方案是 Druid_Common 集群和 Druid_OLAP 集群相互監(jiān)控,互相存儲對方的 metric 信息,然后通過 superset 展示。
圖 18:Druid 的監(jiān)控方案
未來規(guī)劃
Druid 在蘇寧還有很長一段路要走,無論從查詢優(yōu)化方面還是集群管理方面,都有很多事情要做。
查詢優(yōu)化方面:
- 高基數(shù)問題:高基數(shù)查詢一直是 OLAP 查詢的一大痛點(diǎn),新版本雖然支持 limit 下推,但也只是對維度進(jìn)行排序的時候,才能保證準(zhǔn)確性。
- SQL 支持:進(jìn)行 Druid 版本升級,提供豐富的 SQL 查詢接口。
- 精準(zhǔn)去重:目前 Druid 對去重的計(jì)算,無論是 HyperLogLog、ThetaSketch 還是最新版本提供的 HLLSketch 都是非精確的,后面考慮是否可以通過集成 bitmap 解決。
集群管理方面:
- Kafkaindex service 使用:tranquility 的時間窗口限制會造成延遲很大的數(shù)據(jù)丟失,而且實(shí)時 peon 的管理不夠靈活,某些場景下,也會造成數(shù)據(jù)丟失。
而 Kafka index service 的實(shí)時 peon 調(diào)用了 Kafka 底層的 API,管理更靈活,依賴 Kafka 實(shí)現(xiàn)數(shù)據(jù)的不丟不重。
- Datasource 跨集群遷移:Druid 無論是數(shù)據(jù)導(dǎo)入還是數(shù)據(jù)查詢都非常依賴 Zookeeper,當(dāng)集群規(guī)模越來越大,datasource 越來越多的時候,Zookeeper 也許會成為瓶頸。
這樣的話,就需要做 datasource 的遷移,而遷移工作涉及到 datasource 元數(shù)據(jù)和 HDFS 數(shù)據(jù)的遷移,如何讓遷移工作輕量化,是我們需要思考的。
作者:李成露
簡介:蘇寧易購 IT 總部大數(shù)據(jù)中心大數(shù)據(jù)平臺研發(fā)工程師。多年大數(shù)據(jù)底層平臺開發(fā)經(jīng)驗(yàn)。現(xiàn)負(fù)責(zé)蘇寧大數(shù)據(jù)底層平臺的計(jì)算資源調(diào)度平臺以及 Druid 平臺的研發(fā)工作,提供離線計(jì)算平臺和實(shí)時計(jì)算平臺的資源調(diào)度方案,提供基于 Druid 的 OLAP 平臺,為集團(tuán)各種維度指標(biāo)分析業(yè)務(wù)提供穩(wěn)定保障。
【51CTO原創(chuàng)稿件,合作站點(diǎn)轉(zhuǎn)載請注明原文作者和出處為51CTO.com】