Druid是一個開源的、分佈式的、列存儲系統,特別適用於大數據上的(準)實時分析統計。且具備較好的穩定性(Highly Available)。 其相對比較輕量級,文檔很是完善,也比較容易上手。
Druid vs 其餘系統
Druid vs Impala/Shark
Druid和Impala、Shark 的比較基本上能夠歸結爲須要設計什麼樣的系統html
Druid被設計用於:node
- 一直在線的服務
- 獲取實時數據
- 處理slice-n-dice式的即時查詢
查詢速度不一樣:mysql
- Druid是列存儲方式,數據通過壓縮加入到索引結構中,壓縮增長了RAM中的數據存儲能力,可以使RAM適應更多的數據快速存取。索引結構意味着,當添加過濾器來查詢,Druid少作一些處理,將會查詢的更快。
- Impala/Shark能夠認爲是HDFS之上的後臺程序緩存層。 可是他們沒有超越緩存功能,真正的提升查詢速度。
數據的獲取不一樣:算法
- Druid能夠獲取實時數據。
- Impala/Shark是基於HDFS或者其餘後備存儲,限制了數據獲取的速度。
查詢的形式不一樣:sql
- Druid支持時間序列和groupby樣式的查詢,但不支持join。
- Impala/Shark支持SQL樣式的查詢。
Druid vs Elasticsearch
Elasticsearch(ES) 是基於Apache Lucene的搜索服務器。它提供了全文搜索的模式,並提供了訪問原始事件級數據。 Elasticsearch還提供了分析和彙總支持。根據研究,ES在數據獲取和彙集用的資源比在Druid高。json
Druid側重於OLAP工做流程。Druid是高性能(快速彙集和獲取)以較低的成本進行了優化,並支持普遍的分析操做。Druid提供告終構化的事件數據的一些基本的搜索支持。緩存
Segment: Druid中有個重要的數據單位叫segment,其是Druid經過bitmap indexing從raw data生成的(batch or realtime)。segment保證了查詢的速度。能夠本身設置每一個segment對應的數據粒度,這個應用中廣告流量查詢的最小粒度是天,因此天天的數據會被建立成一個segment。注意segment是不可修改的,若是須要修改,只可以修改raw data,從新建立segment了。服務器
架構
![](http://static.javashuo.com/static/loading.gif)
Druid自己包含5個組成部分:Broker nodes, Historical nodes, Realtime nodes, Coordinator Nodes和indexing services. 分別的做用以下:架構
- Broker nodes: 負責響應外部的查詢請求,經過查詢Zookeeper將請求劃分紅segments分別轉發給Historical和Real-time nodes,最終合併並返回查詢結果給外部;
- Historial nodes: 負責’Historical’ segments的存儲和查詢。其會從deep storage中load segments,並響應Broder nodes的請求。Historical nodes一般會在本機同步deep storage上的部分segments,因此即便deep storage不可訪問了,Historical nodes仍是能serve其同步的segments的查詢;
- Real-time nodes: 用於存儲和查詢熱數據,會按期地將數據build成segments移到Historical nodes。通常會使用外部依賴kafka來提升realtime data ingestion的可用性。若是不須要實時ingest數據到cluter中,能夠捨棄Real-time nodes,只定時地batch ingestion數據到deep storage;
- Coordinator nodes: 能夠認爲是Druid中的master,其經過Zookeeper管理Historical和Real-time nodes,且經過Mysql中的metadata管理Segments
- Druid中一般還會起一些indexing services用於數據導入,batch data和streaming data均可以經過給indexing services發請求來導入數據。
Druid還包含3個外部依賴分佈式
- Mysql:存儲Druid中的各類metadata(裏面的數據都是Druid自身建立和插入的),包含3張表:」druid_config」(一般是空的), 「druid_rules」(coordinator nodes使用的一些規則信息,好比哪一個segment從哪一個node去load)和「druid_segments」(存儲每一個segment的metadata信息);
- Deep storage: 存儲segments,Druid目前已經支持本地磁盤,NFS掛載磁盤,HDFS,S3等。Deep Storage的數據有2個來源,一個是batch Ingestion, 另外一個是real-time nodes;
- ZooKeeper: 被Druid用於管理當前cluster的狀態,好比記錄哪些segments從Real-time nodes移到了Historical nodes;
查詢
Druid的查詢是經過給Broker Nodes發送HTTP POST請求(也能夠直接給Historical or Realtime Node),具體可見Druid官方文檔。查詢條件的描述是json文件,查詢的response也是json格式。Druid的查詢包含以下4種:
- Time Boundary Queries: 用於查詢所有數據的時間跨度
- groupBy Queries: 是Druid的最典型查詢方式,很是相似於Mysql的groupBy查詢。query body中幾個元素能夠這麼理解:
- 「aggregation」: 對應mysql」select XX from」部分,即你想查哪些列的聚合結果;
- 「dimensions」: 對應mysql」group by XX」,即你想基於哪些列作聚合;
- 「filter」: 對應mysql」where XX」條件,即過濾條件;
- 「granularity」: 數據聚合的粒度;
- Timeseries queries: 其統計知足filter條件的」rows」上某幾列的聚合結果,相比」groupBy Queries」不指定基於哪幾列進行聚合,效率更高;
- TopN queries: 用於查詢某一列上按照某種metric排序的最多見的N個values;
本文小結
- Druid是一個開源的,分佈式的,列存儲的,適用於實時數據分析的系統,文檔詳細,易於上手;
- Druid在設計時充分考慮到了Highly Available,各類nodes掛掉都不會使得druid中止工做(可是狀態會沒法更新);
- Druid中的各個components之間耦合性低,若是不須要streaming data ingestion徹底能夠忽略realtime node;
- Druid的數據單位Segment是不可修改的,咱們的作法是生成新的segments替換現有的;
- Druid使用Bitmap indexing加速column-store的查詢速度,使用了一個叫作CONCISE的算法來對bitmap indexing進行壓縮,使得生成的segments比原始文本文件小不少;
- 在咱們的應用場景下(一共10幾臺機器,數據大概100列,行數是億級別),平均查詢時間<2秒,是一樣機器數目的Mysql cluter的1/100 ~ 1/10;
- Druid的一些「侷限」:
- Segment的不可修改性簡化了Druid的實現,可是若是你有修改數據的需求,必須從新建立segment,而bitmap indexing的過程是比較耗時的;
- Druid能接受的數據的格式相對簡單,好比不能處理嵌套結構的數據