Druid是什么
Druid在大數據領域已經不是新人了,因此可能很多讀者都已經聽說過Druid,甚至用過Druid,但是未必每個人都真正清晰地了解Druid到底是什么,以及在什么情況下可以用Druid。同時,為了避免大家聽了半天,卻一直陷在各種細節中但仍然不知道到底在聽什么東西,我們還是有必要在開始的時候先總體談一談Druid到底是什么。
簡單來說,Druid 是一個分布式的、支持實時多維OLAP分析的數據處理系統。它既支持高速的數據實時攝入處理,也支持實時且靈活的多維數據分析查詢。因此Druid常用的場景就是大數據背景下、靈活快速的多維OLAP分析。 另外,Druid還有一個關鍵的特點:它支持根據時間戳對數據進行預聚合攝入和聚合分析,因此也有用戶經常在有時序數據處理分析的場景中用到它。
Druid用戶群能夠迅速發展的一個原因是它在大數據背景下集群依然具備的性能和可擴展性。Imply.io公司是Druid創始人創辦的公司,我們可以先通過它公布的一些集群性能介紹圖片來概覽一下Druid集群的一些特點。
數據實時消費能力:
集群的數據規模:
查詢速度:
查詢的并發量:
不難看出,Druid集群在大數據場景下表現優異。
接下來,我們也順便聊一聊Druid的歷史。Druid 單詞來源于西方古羅馬的神話人物, 中文常常翻譯成德魯伊。傳說 Druid 教士精通占卜, 對祭祀禮儀一絲不茍,也擅長于天文歷法、醫藥、天文和文學等。同時, Druid 也 是執法者、吟游詩人和探險家的代名詞。美國廣告技術公司 MetaMarkets 于 2011 年創建了 Druid 項目, 并且于 2012 年開源了 Druid 項目。 Druid 設計之初的想法就是為分析而生,它在處理數據的規模、數據處理的實時性方面, 比傳統的 OLAP 系統有了顯著的性能改進, 而且擁抱主流的開源生態, 包括 Hadoop 等。多年以來, Druid 一直是非常活躍的開源項目。 另外, 阿里巴巴也曾創建過一個開源項目叫作 Druid(簡稱阿里 Druid), 它是一個數據庫連接池的項目。阿里 Druid 和本書討論的 Druid 沒有任何關系,它們解決完全不同的問題。
Druid 的官方網站是 http://druid.io。
技術選型的思考
各個公司在技術選型的時候都會貨比三家,因此在考察Druid的時候也一定會問為什么需要選擇Druid。在本段落中,我們將會對用戶經常會拿來和Druid做比較的組件中的其中幾個來做一些簡單的說明。但是在比較之前,我需要闡明一個基本的觀點:這些不同組件或技術有各自的特點和適用范圍,并沒有一個技術就能徹底替代其它技術這種說法,而本文就僅拿“大數據量下的實時多維OLAP分析”這一場景來做比較。
傳統關系型數據庫:
傳統關系型數據庫(RDBMS)歷史久遠、技術成熟,應用者廣泛,因此采用的學習成本和技術風險也相對較低。典型的RDBMS有Oracle、DB2和MySQL等。從理論上講,因為RDBMS能保證數據的立即一致性,因此特別適合OLTP的場景。然而由于自身的特點所限,RDBMS在可擴展性方面卻表現欠佳,很難輕易和低成本低進行線性擴展以處理更大的數據量。即便現在大多數據庫可以通過分庫分表等方法來使自己可以容納更多的數據,但是這種方式也存在著管理復雜和成本高昂等明顯短板,因此實際應用中也存在著數據量的天花板。因此,考慮既定的場景“大數據量下的實時多維OLAP分析”,RDBMS首先就很難跨過“大數據量”這一關。
Massively Parallel Processing 數據庫:
大規模并行處理(MPP,massively parallel processing)數據庫的代表是Teradata、Greenplum、Vertica和Impala等。它們的優點是適合將RDBMS的應用擴展到集群范圍,以處理更大的數據量,同時繼承了RDBMS的很多優點。然而,它依然沒法從根本上滿足處理海量數據的需求,因為它的系統性能很難隨集群的擴展一直線性增長,所以其集群擴展性有限;而且它的集群容錯性也有限,比如當其Raid磁盤出錯后可能會導致其節點響應速度變慢。
ElasticSearch:
ElasticSearch幾乎已經是當下實時上的搜索服務器標準,而它與Logstash和Kibana的搭配(簡稱ELK)也是應用很廣的套件組合。ElasticSearch有很強的文檔索引和全文檢索的能力,也支持豐富的查詢功能(包括聚合查詢),并且擴展性好,因此很多用戶也常常在拿Elasticsearch和Druid做比較。然而,在我們的既定場景下,Elasticsearch有著其明顯的短板:不支持預聚合;組合查詢性能欠佳;等等。
OpenTSDB:
OpenTSDB是一款的時序數據庫,且基于用戶廣泛的HBase數據庫,因此有著較多的客戶群。它的優勢在于查詢速度快、擴展性好,且schemaless。然而,它也有一些缺點:查詢的維度組合數量需要提前確定好,即通過存儲中的tag組合來確定,因此缺乏了靈活性;數據冗余度大;基于HBase,對于運維人員能力要求較高;等等。
Kylin:
Kylin出自eBay,并且是Apache的新頂級項目,是一款非常不錯的分布式OLAP系統。它的優勢在于項目來自于豐富的實踐、發展前景光明、直接利用了成熟的Hadoop體系(HBase和Hive等)、cube模型支持較好、查詢速度快速等。但它也在一些方面有著自己的局限,比如:查詢的維度組合數量需要提前確定好,不適合即席查詢分析;預計算量大,資源消耗多;集群依賴較多,如HBase和Hive等,屬于重量級方案,因此運維成本也較高;等等。
Druid基礎知識
數據存儲格式
Druid自己有著數據存儲的邏輯和格式(主要是DataSource和Segment),而且其架構和實現也是圍繞著它們而進行的,因此我們有必要對其數據存儲格式做一些介紹。
首先,若與傳統的關系型數據庫管理系統(RDBMS)做比較,Druid 的 DataSource 可以理解為 RDBMS 中的表(Table)。正如前面章節中所介紹的,DataSource 的結構包含以下幾個方面。
時間列(TimeStamp):表明每行數據的時間值,默認使用 UTC 時間格式且精確到毫秒級別。這個列是數據聚合與范圍查詢的重要維度。
維度列(Dimension): 度來自于OLAP的概念,用來標識數據行的各個類別信息。
指標列(Metric):指標對應于OLAP概念中的Fact,是用于聚合和計算的列這些指標列通常是一些數字,計算操作通常包括 Count、Sum 和 Mean 等。
無論是實時數據消費還是批量數據處理,Druid 在基于 DataSource 結構存儲數據時即可選擇對任意的指標列進行聚合(Roll Up)操作。相對于其他時序數據庫,Druid 在數據存儲時便可對數據進行聚合操作是其一大特點, 并且該特點使得 Druid 不僅能夠節省存儲空間,而且能夠提高聚合查詢的效率。
DataSource 是一個邏輯概念,Segment 卻是數據的實際物理存儲格式,Druid 正是通過 Segment 實現了對數據的橫縱向切割(Slice and Dice)操作。從數據按時間分布的角度來看, 通過參數 segmentGranularity 的設置,Druid 將不同時間范圍內的數據存儲在不同的 Segment 數據塊中,這便是所謂的數據橫向切割。這種設計為 Druid 帶來一個顯而易見的優點:按時間范圍查詢數據時,僅需要訪問對應時間段內的這些 Segment 數據塊,而不需要進行全表數據范圍查詢,這使效率得到了極大的提高。
同時,在 Segment 中也面向列進行數據壓縮存儲,這便是所謂的數據縱向切割。而且對Segment 中的維度列使用了 Bitmap 技術對其數據的訪問進行了優化。其中,Druid會為每一維度列存儲所有列值、創建字典(用來存儲所有列值對應的ID)以及為每一個列值創建其bitmap索引以幫助快速定位哪些行擁有該列值。
基于實時節點的架構
Druid早的架構是基于實時節點(Realtime Node)的。它的特點是有專門的實時節點來負責消費數據。
Druid自身包含以下 4 類節點。
實時節點(RealtimeNode):即時攝入實時數據,以及生成Segment數據文件。
歷史節點(HistoricalNode):加載已生成好的數據文件,以供數據查詢。
查詢節點(Broker Node):對外提供數據查詢服務,并同時從實時節點與歷史節點查詢數據,合并后返回給調用方。
協調節點(CoordinatorNode):負責歷史節點的數據負載均衡,以及通過規則(Rule) 管理數據的生命周期。
同時,集群還包含以下三類外部依賴。
元數據庫(Metastore):存儲Druid集群的原數據信息,比如Segment的相關信息,一般用 MySQL 或 PostgreSQL。
分布式協調服務(Coordination):為Druid集群提供一致性協調服務的組件,通常為Zookeeper。
數據文件存儲庫(DeepStorage):存放生成的Segment數據文件,并供歷史節點下載 對于單節點集群可以是本地磁盤,而對于分布式集群一般是 HDFS 或 NFS。
從數據流轉的角度來看,數據從架構圖的左側進入系統,分為實時流數據與批量數據。實時流數據會被實時節點消費,然后實時節點將生成的 Segment 數據文件上傳到數據文件存儲庫;而批量數據經過 Druid 集群消費后會被直接上傳到數據文件存儲庫。同時,查詢節點會響應外部的查詢請求,并將分別從實時節點與歷史節點查詢到的結果合并后返回。
基于Indexing Service的架構
在基于Indexing Service的架構中,實時節點被廢棄掉了,轉而代之的Overlord節點和MiddleManager節點。其中,Overlord節點作為索引服務的主節點,對外負責接收任務請求,對內負責將任務分解并下發到從節點即MiddleManager節點上。而MiddleManager節點就是索引服務的工作節點,負責接收統治節點分配的任務,然后啟動相關苦工(Peon)即獨立的 JVM 來完成具體的任務。這樣的架構實際與 Hadoop Yarn 很像。
較之基于實時節點的架構,基于Indexing Service的架構有不少優點:除了對數據能夠用 pull 的方式外,還支持 push 的方式;不同于手工編寫數據消費配置文件的方式,可以通過 API 的編程方式來靈活定義任務配置;可以更靈活地管理與使用系統資源;可以完成 Segment 副本數量的控制;能夠靈活完成跟 Segment 數據文件相關的所有操作,如合并、刪除 Segment 數據文件等。
查詢
Druid的默認提供了HTTP REST 風格的查詢接口。一個典型的 curl 命令如下: curl -X POST ':/druid/v2/?pretty' -H 'Content-Type:application /json' -d @ 。
其中,queryablehost:port 為查詢節點的 IP 地址和端口;queryjson_ le為POST到查詢節點的查詢請求。
為了便于用戶進行靈活的OLAP分析,Druid提供了豐富的查詢接口,比如過濾器、聚合器和后置聚合器等。由于這部分內容比較好理解,而且Druid官網上有詳細的介紹,因此本文就不再過多說明,這里僅聚一個實際的查詢例子如下:
{
"queryType": "timeseries",
"dataSource": "visitor_statistics",
"granularity": "all",
"filter": {
"type": "and",
"fields": [
{
"type": "selector",
"dimension": "host",
"value": "www.mejia.wang"
},
{
}
]
},
"aggregations": [
{
"type": "longSum",
"name": "pv",
"fieldName": "counbt"
},
{
},
{
"type": "hyperUnique",
"name": "new_visitor_count",
"fieldName": "new_visit_count"
},
{
}
],
"postAggregations": [
{
"type": "arithmetic",
"name": "new_visitor_rate",
"fn": "/",
"fields": [
{
"type": "hyperUniqueCardinality",
"fieldName": "new_visitor_count"
},
{
"fieldName": "visitor_count"
}
]
},
{
"type": "arithmetic",
"name": "click_rate",
"fn": "/",
"fields": [
{
"type": "hyperUniqueCardinality",
"fieldName": "click_visitor_count"
},
{
"type": "hyperUnique",
"name": "click_visitor_count",
"fieldName": "click_visit_count""type": "hyperUniqueCardinality",
"type": "hyperUniqueCardinality",
"fieldName": "visitor_count"
}
]
}
],
"intervals": [
"2016-08-07T00:00:00+08:00/2016-09-05T23:59:59+08:00"
]
}
返回結果可能如下:
[
{
"timestamp": "2016-08-27T16:00:00.000Z",
"result": {
"pv": 30.000000061295435,
"visit_count": 5.006113467958146,
"new_visitor_count": 0,
"click_visitor_count": 5.006113467958146,
"new_visitor_rate": 0,
"click_rate": 1,
}
}
]
豐富的輔助功能
Druid除了基本的核心數據消費和查詢功能外,還提供了豐富的輔助功能,以幫助用戶更好地基于Druid完成數據處理工作。本文簡單列舉幾個:
DataSketches aggregator:近似計算COUNT DISTINCT等問題,如PV、留存等;精度可調節。
Multi-value dimensions:對于同一維度列,允許不同行擁有不同數量的數據值:這使得Druid也能夠有類似schemaless的功能。
{"timestamp": "2011-01-12T00:00:00.000Z", "tags": ["t1","t2","t3"]} #row1 {"timestamp": "2011-01-13T00:00:00.000Z", "tags": ["t3","t4","t5"]} #row2
Router Node:協助Broker Node實現負載均衡。
Query Caching:幫助提升查詢性能,可以用在Historical Node或Broker Node上。
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。