Druid 介紹
說起 Druid,大家首先想到的是阿里的 Druid 數據庫連接池父款,而本文介紹的 Druid 是一個在大數據場景下的解決方案,是需要在復雜的海量數據下進行交互式實時數據展現的 BI/OLAP 工具。
它有三個特點:
- 處理的數據量規(guī)模較大返顺。
- 可以進行數據的實時查詢展示禀苦。
- 它的查詢模式是交互式的,這也說明其查詢并發(fā)能力有限遂鹊。
目前 Druid 廣泛應用在國內外各個公司振乏,比如阿里,滴滴秉扑,知乎慧邮,360能岩,eBay撰洗,Hulu 等。
Druid 之所以能夠在 OLAP 家族中占據一席之地果正,主要依賴其強大的 MPP 架構設計吨娜,關于它的架構脓匿,這里就不展開描述了,感興趣的同學可以登陸官網 druid.io 進行了解宦赠。
除了 MPP 架構外陪毡,它還運用到了四點重要的技術,分別是:
- 預聚合
- 列式存儲
- 字典編碼
- 位圖索引
預聚合算是 Druid 的一個非常大的亮點勾扭,通過預聚合可以減少數據的存儲以及避免查詢時很多不必要的計算毡琉。
由于 OLAP 的分析場景大多只關心某個列或者某幾個列的指標計算,因此數據非常適合列式存儲妙色。
在列式存儲的基礎之上桅滋,再加上字段編碼,能夠有效的提升數據的壓縮率身辨,然后位圖索引讓很多查詢最終直接轉化成計算機層面的位計算丐谋,提升查詢效率。
Druid 既然是 OLAP 工具煌珊,那它和其他 OLAP 工具有哪些差異呢?
從上圖可以看出号俐,Kylin 和 Druid 整體上相比較其他兩個還是很有優(yōu)勢的:
相比較 Kylin,Druid 沒有模型管理和 cube 管理的能力定庵,Kylin 無法提供實時查詢吏饿。
相比較 ES,Druid 的優(yōu)勢在于聚合計算蔬浙,ES 的優(yōu)勢在于查明細猪落,在蘇寧,對 Druid 的使用畴博,一般應用在需要對數據進行實時聚合查詢的場景笨忌。
Druid的應用場景
門店 App 系統(tǒng)
門店 App 系統(tǒng)是一款集數據服務、銷售開單俱病、會員營銷官疲、收發(fā)盤退杂曲、績效管理、V 購用戶溝通袁余、學習中心等于一體的門店店員移動工作平臺,其銷售界面如下所示:
門店 App 業(yè)務大致情況如下:
- 數據量:保存近幾年的數據咱揍。
- 數據接入方式:Kafka 實時數據接入颖榜,隔天離線數據覆蓋昨天數據。
- 查詢方式:實時查詢煤裙。
- 業(yè)務實現:topN 實現銷售額曲線展示掩完,groupby 分組樓層客流分布,timeserise 做天匯總硼砰。
報表系統(tǒng)
大致情況如下:
- 數據量:保存近幾年數據且蓬。
- 數據接入方式:Kafka 實時數據接入。
- 查詢方式:實時查詢题翰。
- 業(yè)務實現:topN 實現銷售餅圖展示恶阴,groupby 分組實現大區(qū)銷售排名。
基于 OLAP 引擎的平臺架構
為保證數據的一致性和統(tǒng)一性豹障,該平臺基于 OLAP 引擎冯事,為集團各個業(yè)務提供統(tǒng)一的維度指標分析系統(tǒng):
- 百川系統(tǒng)通過 OLAP 引擎構建模型,OLAP 引擎根據業(yè)務需求血公,將模型拆分成若干個 cube昵仅,存儲到底層的 Druid,Hive累魔,PG 和 ES摔笤。我們稱這個過程為模型加速,另外垦写,百川系統(tǒng)自身會構建各種各樣的指標吕世。
- 業(yè)務方,比如天工梯澜,諸葛等系統(tǒng)通過百川提供的指標寞冯,選擇其中一個或多個進行報表的構建,其查詢請求會發(fā)送到百川系統(tǒng)晚伙。
- 百川系統(tǒng)構造 SQL 語句吮龄,再把請求發(fā)送到 OLAP 引擎,OLAP 引擎通過底層的 Spark 平臺咆疗,解析 SQL 語句漓帚,將請求路由到 Druid,ES午磁,Hive 和 PG尝抖,其中毡们,時序化數據的聚合查詢,將路由到 Druid 平臺昧辽,最后查詢結果一層一層匯總到上層的業(yè)務系統(tǒng)衙熔。
- 整個系統(tǒng)的監(jiān)控,通過云跡系統(tǒng)搅荞、華佗系統(tǒng)等進行監(jiān)控红氯,將系統(tǒng)日志接入云跡,將系統(tǒng)的 metric 信息接入華佗咕痛。
隨著 Druid 平臺建設的不斷推進痢甘,使用 Druid 的業(yè)務也越來越多,在使用的過程中也會遇到各種各樣的問題茉贡,下文總結了蘇寧業(yè)務開發(fā)人員在使用 Druid 中遇到的一些問題塞栅,希望對正在閱讀本文的讀者有些幫助。
Druid 使用建議
本小節(jié)主要想結合實際問題腔丧,給大家提供一些 Druid 的使用建議放椰,供大家參考。
①什么樣的業(yè)務適合用 Druid?
建議如下:
- 時序化數據:Druid 可以理解為時序數據庫愉粤,所有的數據必須有時間字段庄敛。
- 實時數據接入可容忍丟數據(tranquility):目前 tranquility 有丟數據的風險,所以建議實時和離線一起用科汗,實時接當天數據藻烤,離線第二天把今天的數據全部覆蓋,保證數據完備性头滔。
- OLAP 查詢而不是 OLTP 查詢:Druid 查詢并發(fā)有限怖亭,不適合 OLTP 查詢。
- 非精確的去重計算:目前 Druid 的去重都是非精確的坤检。
- 無 Join 操作:Druid 適合處理星型模型的數據兴猩,不支持關聯操作。
- 數據沒有 update 更新操作早歇,只對 segment 粒度進行覆蓋:由于時序化數據的特點倾芝,Druid 不支持數據的更新。
②如何設置合理的 Granularity?
首先解釋下 segmentGranularity 和 queryGranularity箭跳,前者是 segment 的組成粒度晨另,后者是 segment 的聚合粒度。
要求 queryGranularity 小于等于 segmentGranularity谱姓,然后在數據導入時借尿,按照下面的規(guī)則進行設置。
segmentGranularity(離線數據導入的設置):
- 導入的數據是天級別以內的:“hour”或者“day”。
- 導入的數據是天級別以上的:“day”路翻。
- 導入的數據是年級別以上的:“month”狈癞。
需要說明的是,這里我們僅僅是簡單的通過 intervals 進行 segmentGranularity 的設置茂契,更加合理的做法應該是結合每個 segment 的大小以及查詢的復雜度進行綜合衡量蝶桶。
考慮到 tranquility 實時任務的特殊性和數據的安全性,我們建議實時數據導入時掉冶,segmentGranularity 設置成“hour”莫瞬。
queryGranularity:根據業(yè)務查詢最小粒度和查詢復雜度來定,假設查詢只需要到小時粒度郭蕉,則該參數設置為“hour”。
③需要去重的維度到底需不需要定義到維度列中?
如果去重的維度只需要去重計算喂江,沒有其他的作用召锈,譬如進行過濾或者作為分組字段,我們建議不要添加到維度列中获询,因為不添加的話涨岁,這樣數據的預聚合效果更好。
④如何選擇查詢方式?
常用的三種查詢:
- 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 新版本進行了優(yōu)化秉撇,雖然可以下推,但是對于指標的排序是不準確的)秋泄,所以單維度的分組查詢琐馆,盡量用 topN 查詢。
我們做的工作
從 Druid 引入蘇寧之后恒序,不久便承擔起了 OLAP 分析的重任瘦麸,作為底層核心引擎支撐模型和指標服務,并為集團各條業(yè)務線的 OLAP 分析服務歧胁,在過去的時間里滋饲,我們做了很多工作,本文列舉一些進行說明喊巍。
①OCEP(Druid 集群前置 proxy)
OCEP 是 Druid 集群一個前置 proxy屠缭,通過它來提供更加完備的 Druid 集群化和服務化能力,并解決當前 Druid 服務存在的各種問題崭参。
它提供的功能主要有:
- 訪問鑒權(針對每個 datasource 提供 token 訪問鑒權勿她,保證數據安全)。
- 訪問審計(對每個查詢都會生成唯一的 queryId阵翎,提供完整的請求來源)逢并。
- 請求攔截(對非預期的訪問之剧,制定攔截策略,細化到具體的 datasource 和查詢語句)砍聊。
- 請求路由(根據集群名稱和 datasource背稼,將請求路由到指定的 Druid 集群,并根據后端 broker 的壓力玻蝌,將請求負載均衡各個 broker 上)蟹肘。
- 服務隔離(可設置策略,對于不同的 datasource 的請求俯树,可路由到指定的 broker 上帘腹,實現 broker 隔離)。
②Druid 查詢客戶端
官方提供的查詢方式是通過編寫 Json 文件许饿,以 HTTP 的方式請求 Druid阳欲,然而這種方式的缺點也很明顯,首先 Json 內容書寫繁瑣陋率,格式極易寫錯球化,另外在 Java 開發(fā)時,出現問題不利于定位瓦糟。
于是我們封裝了一層 Java API筒愚,如下圖:
③資源隔離
不同業(yè)務的數據量有大小之分以及對服務穩(wěn)定性要求不一樣,我們通過以下三點實現業(yè)務層面的隔離:
- Historical 分組:集群設置不同的 tier菩浙,存儲不同的業(yè)務數據巢掺。
- Broker 隔離:通過 OCEP 設置 datasource 白名單,不同的 broker 只提供某個或某幾個 datasource 的查詢劲蜻。
- 冷熱數據隔離:通過設置 datasource 的 rule址遇,將冷熱數據分別存儲在不同的 tier 中。
- Druid 白名單控制斋竞。
集群穩(wěn)定性壓倒一切倔约,防止控制以外的機器對集群進行無效查詢和攻擊,我們通過增加一個 whitelist 的 extension坝初,以模塊的方式在服務端進行白名單的控制浸剩。
并且可以針對不同的服務進行控制,將 whitelist 的配置文件寫在 Druid 的 metadata 的 config 表中鳄袍,實現動態(tài)更新绢要。
④Druid 離線導入時對 intervals 的控制
有些離線導入的任務,占用了 YARN 太多的資源拗小,個別任務消耗了上千個或者上萬的 container 資源重罪,分析發(fā)現是由于業(yè)務設置的 segmentGranularity 不合理,最終會導致 segment 過多,產生很多 HDFS 小文件剿配。
于是我們在 overlord 服務端搅幅,增加參數“druid.indexer.intervals.maxLimit”,對離線任務進行判斷呼胚。
如果 segmentGranularity 和 interval 設置的不合理茄唐,將禁止提交。譬如蝇更,segmentGranularity 設置的是小時沪编,interval 設置的間隔是 1 年,這種是不合理的年扩,服務端將禁止數據導入蚁廓。
⑤Coordinator 自動 merge segment 時啟動 task 的并發(fā)數控制
在集群中,我們打開了 coordinator 自動 merge segment 的功能厨幻,coordinator 默認每隔 30 分鐘相嵌,啟動 merge 線程,掃描所有的 datasource克胳,將過小的 segment 按要求進行合并。
每當一批 segment 符合 merge 要求了圈匆,就會請求 overlord 進行啟動 merge task漠另。
如果集群內小 segment 很多,merge task 將啟動無數個跃赚,堵塞 middleManager 的 peon 資源笆搓,我們增加限制 merge task 的并發(fā)數的參數,保證每次 merge 線程只啟動一定數量的 task纬傲。
⑥Druid 監(jiān)控
監(jiān)控對于任何一個系統(tǒng)而言都是非常重要的满败,可以幫助我們提前預知系統(tǒng)的健康狀況,Druid 的監(jiān)控主要有兩點叹括,業(yè)務查詢情況和平臺運行情況算墨。
前者主要包括 datasource 的查詢量、查詢耗時汁雷、網絡流量等;后者主要包括各個服務的 gc 情況净嘀、cpu 和內存使用情況、空閑 Jetty 線程數等侠讯。
我們的監(jiān)控方案是 Druid_Common 集群和 Druid_OLAP 集群相互監(jiān)控挖藏,互相存儲對方的 metric 信息,然后通過 superset 展示厢漩。
未來規(guī)劃
Druid 在蘇寧還有很長一段路要走膜眠,無論從查詢優(yōu)化方面還是集群管理方面,都有很多事情要做。
查詢優(yōu)化方面:
- 高基數問題:高基數查詢一直是 OLAP 查詢的一大痛點宵膨,新版本雖然支持 limit 下推架谎,但也只是對維度進行排序的時候,才能保證準確性柄驻。
- SQL 支持:進行 Druid 版本升級狐树,提供豐富的 SQL 查詢接口。
- 精準去重:目前 Druid 對去重的計算鸿脓,無論是 HyperLogLog抑钟、ThetaSketch 還是最新版本提供的 HLLSketch 都是非精確的,后面考慮是否可以通過集成 bitmap 解決野哭。
集群管理方面:
- Kafkaindex service 使用:tranquility 的時間窗口限制會造成延遲很大的數據丟失在塔,而且實時 peon 的管理不夠靈活,某些場景下拨黔,也會造成數據丟失蛔溃。
而 Kafka index service 的實時 peon 調用了 Kafka 底層的 API,管理更靈活篱蝇,依賴 Kafka 實現數據的不丟不重贺待。
- Datasource 跨集群遷移:Druid 無論是數據導入還是數據查詢都非常依賴 Zookeeper,當集群規(guī)模越來越大零截,datasource 越來越多的時候麸塞,Zookeeper 也許會成為瓶頸。
這樣的話涧衙,就需要做 datasource 的遷移哪工,而遷移工作涉及到 datasource 元數據和 HDFS 數據的遷移,如何讓遷移工作輕量化弧哎,是我們需要思考的雁比。