Apache Druid —當代大數據分析的必要條件

術語"大數據"是指具有高容量,高速度和多樣化的數據的數字存儲。 大數據分析是使用軟件來發現那些大型數據存儲中的趨勢,模式,相關性或其他有用見解的過程。 Apache Druid基本上有能力證明自己是構建大數據分析平臺的骨幹之一。

Apache Druid —當代大數據分析的必要條件

根據Wikipedia的介紹,Druid是一種用Java編寫的面向列的開源分佈式數據存儲。 Druid旨在快速提取大量事件數據,並在數據之上提供低延遲查詢。

Apache Druid —當代大數據分析的必要條件

Druid的核心設計結合了數據倉庫,時間序列數據庫和搜索系統的想法,從而創建了一個統一的系統,可以對廣泛的用例進行實時分析。

Druid將這三個系統中的每個系統的關鍵特徵合併到其接收層,存儲格式,查詢層和核心體系結構中。

Druid的主要特點:

列式存儲:

Druid分別存儲和壓縮每一列,只需要讀取特定查詢所需的內容即可,這支持快速掃描,排名和按組。

本機搜索索引:

關於Druid的索引實現的一個重要方面是,它使用了倒排索引。 反向索引是一種索引數據結構,用於存儲從內容(例如單詞或數字)到其在一個文檔或一組文檔中的位置的映射。 倒排索引的目的是允許快速的全文本搜索,但當將文檔添加到數據庫時,這樣做會增加處理量。

反向索引有兩種類型:記錄級反向索引包含每個單詞的文檔引用列表。 單詞級倒排索引還包含文檔中每個單詞的位置。

Druid為字符串值創建倒排索引,以加快搜索和過濾操作。

流式處理和批量攝取:

德魯伊允許其用戶利用Lambda Architecture的工作原理。 Lambda體系結構是一種數據處理體系結構,旨在通過利用批處理和流處理方法來處理大量數據。

Druid提供了到Apache Kafka的連接器,用於通過流和HDFS實時提取數據,提供用於批量提取的AWS S3。 它還支持其他流傳輸和批處理管道以進行數據提取。

時間優化的分區:

與時間序列數據庫類似,Druid按時間對數據進行智能分區,以實現快速的面向時間的查詢。

與許多傳統系統不同,Druid可以選擇在攝取數據時預聚合數據。 此預聚合步驟稱為彙總,可以節省大量存儲空間。 彙總是對選定的一組列進行的第一級聚合操作,可減少存儲數據的大小。 在彙總活動期間,輸入行按時間戳和維度列進行分組,並在度量標準列上進行彙總彙總。

啟用匯總後,具有相同維度和時間戳的所有行(在基於queryGranularity的截斷之後)都可以摺疊或彙總為Druid中的單個行。

靈活的列和SQL支持:

Druid可以優雅地處理不斷髮展的模式和嵌套數據。 在舊版dataSchema中,flattenSpec位於dataSchema→解析器→parseSpec→flattenSpec中,負責彌合潛在嵌套的輸入數據(例如JSON,Avro等)與Druid的平面數據模型之間的差距。

除了基於本機JSON的本地語言外,Druid還通過HTTP或JDBC講SQL。

Druid組件和工作原理:

Druid具有多進程,分佈式架構,旨在實現雲友好且易於操作。 每種Druid進程類型都可以獨立配置和擴展,從而為您的集群提供最大的靈活性。 這種設計還提高了容錯能力:一個組件的故障不會立即影響其他組件。

Apache Druid —當代大數據分析的必要條件

Druid有幾種過程類型,下面簡要描述:

協調人:

負責管理集群上的數據可用性。 Druid協調員流程主要負責部門管理和分配。 更具體地說,Druid協調器進程與歷史進程進行通信,以基於配置加載或刪除段。

Druid協調器負責加載新段,刪除過時的段,管理段複製以及平衡段負載和段壓縮。

Druid協調器維護與Zookeeper集群的連接以獲取當前集群信息。

協調器還維護與數據庫的連接,該數據庫包含有關可用段和規則的信息。 可用的段存儲在段表中,並列出應在集群中加載的所有段。 規則存儲在規則表中,並指示應如何處理段。

段壓縮:

在每次運行期間,Druid協調器通過合併小段或拆分大段來壓縮數據段。

當未根據段大小優化段時,這可能會降低查詢性能,這很有用。

壓縮任務可能由於以下原因而失敗。

· 如果壓縮任務的輸入段在啟動之前被刪除或遮蓋,則該壓縮任務將立即失敗。

· 如果較高優先級的任務在與壓縮任務的時間間隔重疊的時間間隔內獲取了時間塊鎖,則壓縮任務將失敗。

一旦壓縮任務失敗,協調器將簡單地再次檢查失敗任務間隔內的段,並在下一次運行中發出另一個壓縮任務。

霸王:

負責控制數據提取工作負載的分配。 霸主進程負責接受任務,協調任務分配,圍繞任務創建鎖以及將狀態返回給調用方。

可以將霸王配置為以以下兩種模式之一運行:本地或遠程(默認為本地)。

在本地模式下,Overlord還負責創建用於執行任務的Peon。

在本地模式下運行霸主時,還必須提供所有MiddleManager和Peon配置。 本地模式通常用於簡單的工作流程。

在遠程模式下,Overlord和MiddleManager在單獨的進程中運行,並且可以在不同的服務器上單獨運行。 如果我們打算將索引服務用作所有Druid索引的單個端點,則建議使用此模式。

中層經理:

MiddleManager進程是執行提交任務的工作進程。 中級經理將任務轉發給在單獨的JVM中運行的Peons。 我們為任務分配單獨的JVM的原因是為了資源和日誌隔離。

每個Peon一次只能運行一個任務,但是,MiddleManager可能有多個Peon。

索引服務:

Apache Druid索引服務是一種高可用性的分佈式服務,可運行與索引相關的任務。

索引任務創建(有時銷燬)Druid段。 索引服務具有類似主/從的體系結構。

Apache Druid —當代大數據分析的必要條件

索引服務由三個主要組件組成:

· 一個可以運行單個任務的Peon組件。

· 管理Peons的中間管理器組件。

· 一個Overlord組件,用於管理向MiddleManager的任務分配。 霸主和MiddleManager可以在同一進程上運行,也可以跨多個進程運行,而MiddleManager和Peons始終在同一進程上運行。

經紀人:

負責處理來自外部客戶端的Druid查詢。 當我們在分佈式集群上運行Druid時,Broker是路由查詢的過程。 它瞭解發佈到ZooKeeper的元數據,該元數據涉及哪些段存在於哪些流程中並路由查詢,以使它們命中正確的流程。 此過程還將所有單個過程的結果集合並在一起。

查詢轉發:

Druid Broker確定要轉發查詢的流程,Broker流程首先根據Zookeeper中的信息構建世界視圖。 Zookeeper維護有關"歷史記錄和流式提取Peon進程"以及它們正在服務的段的信息。

對於Zookeeper中的每個數據源,"代理"流程都會構建一個時間段以及為這些數據段提供服務的流程。 當收到針對特定數據源和時間間隔的查詢時,Broker流程將對與查詢間隔相關的查詢數據源的時間軸進行查詢,並檢索包含查詢數據的流程。 然後,Broker進程將查詢向下轉發到選定的進程。

快取

代理進程使用具有LRU緩存無效策略的緩存。 Broker緩存存儲每個段的結果。 緩存可以是每個Broker進程的本地緩存,也可以使用外部分佈式緩存(例如memcached)在多個進程之間共享。

代理程序每次接收到查詢時,都會首先將查詢映射到一組細分。 這些細分結果的子集可能已經存在於緩存中,並且可以直接從緩存中提取結果。 對於緩存中不存在的任何段結果,代理進程將把查詢轉發到歷史進程。

歷史進程返回其結果後,代理會將這些結果存儲在緩存中。 實時段永遠不會被緩存,因此對實時數據的請求將始終轉發到實時進程。 實時數據一直在變化,因此緩存結果將是不可靠的。

歷史:

Druid歷史進程負責存儲可查詢的數據。 每個"歷史"進程都保持與Zookeeper的恆定連接,並監視一組可配置的Zookeeper路徑以獲取新的細分信息。 歷史過程並不直接與彼此或與協調器過程進行通信,而是依靠Zookeeper進行協調。

如何加載和服務細分:

協調器流程負責為歷史流程分配新的細分。 通過在與"歷史"進程關聯的加載隊列路徑下創建一個臨時的Zookeeper條目來完成分配。

當"歷史記錄"進程在其加載隊列路徑中注意到一個新的加載隊列條目時,它將首先在本地磁盤目錄(緩存)中查找有關段的信息。 如果緩存中不存在有關該段的信息,則"歷史"進程將下載有關新段的元數據以從Zookeeper服務。 該元數據包括有關該段在深度存儲中的位置以及如何解壓縮和處理該段的規範。 歷史進程完成對片段的處理後,將在Zookeeper中與該過程關聯的服務片段路徑下宣佈片段。 此時,該段可供查詢。

段緩存及其工作方式:

當"歷史記錄"進程在其加載隊列路徑中注意到一個新的段條目時,"歷史記錄"進程首先檢查其本地磁盤上的可配置緩存目錄,以查看該段之前是否已下載。 如果本地緩存條目已經存在,則Historical(歷史)進程將直接從磁盤讀取段二進制文件並加載該段。

首次啟動歷史記錄過程時,也會利用段緩存。 啟動時,歷史進程將搜索其緩存目錄,並立即加載並提供找到的所有段。 此功能允許歷史進程聯機後立即對其進行查詢。

Druid的攝取方法

下表列出了Druid最常用的數據提取方法,並進行了比較,以幫助我們選擇最適合自己需要的方法。 每種攝取方法都支持其自己的源系統集。

流媒體

最推薦,最流行的流媒體攝取方法是直接從Kafka讀取的Kafka Indexing Service。 如果我們更喜歡Amazon Kinesis,則Kinesis索引服務也可以很好地工作。

下表比較了主要可用選項:

Apache Druid —當代大數據分析的必要條件

批處理

從文件批量加載時,應使用一次性任務,並且有三個選項:index_parallel(本地批處理;並行),index_hadoop(基於Hadoop)或索引(本地批處理;單任務)。

通常,我們建議在滿足您需求時進行本機批處理,因為它的設置較為簡單(它不依賴於外部Hadoop集群)。 但是,在某些情況下,基於Hadoop的批量提取可能是一個更好的選擇,例如,當您已經有一個正在運行的Hadoop群集並且想要使用現有群集的群集資源進行批量提取時。

下表比較了三個可用選項:

Apache Druid —當代大數據分析的必要條件

Druid的攝入規格:

無論我們採用哪種攝取方式,都將使用一次性任務或正在進行的"監督程序"(隨時間運行並監督一組任務)將數據加載到Druid中。 無論如何,任務或管理者定義的一部分是攝入規範。

攝取規範包括三個主要組成部分:

· dataSchema,用於配置數據源名稱,主時間戳,維度,指標以及轉換和過濾器(如果需要)。

· ioConfig,它告訴Druid如何連接到源系統以及如何解析數據。 有關更多信息,請參閱每種攝取方法的文檔。

· tuningConfig,用於控制特定於每種攝取方法的各種調整參數。

我在下面共享了兩種Ingestion-Spec,其中我們使用實時Kafka流傳輸和通過來自AWS S3的文件的批處理將數據提取到同一數據源中。

Apache Druid —當代大數據分析的必要條件

> Ingestion-Spec sample for Realtime Druid Ingestion for Kafka Indexing Service

Apache Druid —當代大數據分析的必要條件

> Ingestion-Spec for Native Batch Ingestion into Druid from a file stored on AWS S3

Druid的數據模型

數據源

德魯伊數據存儲在數據源中,該數據源類似於傳統RDBMS中的表。 德魯伊提供了一個獨特的數據建模系統,該系統與關係模型和時間序列模型都有相似之處。

主時間戳

Druid模式必須始終包含主時間戳。 主時間戳用於對數據進行分區和排序。 Druid查詢能夠快速識別和檢索與主要時間戳列的時間範圍相對應的數據。 Druid還能夠使用主時間戳列進行基於時間的數據管理操作,例如刪除時間塊,覆蓋時間塊和基於時間的保留規則。

基於timestampSpec解析主時間戳。 此外,granularitySpec控制基於主時間戳的其他重要操作。

維度

維度是按原樣存儲並且可以用於任何目的的列。 我們可以在查詢時以臨時方式對維度進行分組,過濾或應用聚合器。

如果我們在禁用匯總功能的情況下運行,那麼維度集將被視為要吸收的一組列,並且其行為與我們從不支持彙總功能的典型數據庫中所期望的完全一樣。

尺寸是通過DimensionsSpec配置的。

指標

指標是以聚合形式存儲的列。 啟用匯總時,它們最有用。 指定度量標準後,我們可以為Druid選擇一個聚合函數,以在攝取期間將其應用於每一行。

度量是通過metricsSpec配置的。

分區

數據源中段的最佳分區和排序可能會對佔用空間和性能產生重大影響。

Druid數據源始終按時間劃分為多個時間塊,每個時間塊包含一個或多個段。 此分區針對所有攝取方法進行,並且基於攝取規範的dataSchema的segmentGranularity參數。

使用根據您選擇的攝取類型而變化的選項,還可以進一步細分特定時間塊內的細分。 通常,使用特定維度進行此次級分區將提高局部性,這意味著具有相同維度值的行將存儲在一起並可以快速訪問。

區隔

Apache Druid將其索引存儲在段文件中,該段文件按時間進行分區。 在基本設置中,將為每個時間間隔創建一個分段文件,其中該時間間隔可在granularitySpec的segmentGranularity參數中配置。

為了使Druid在繁重的查詢負載下正常運行,重要的是,段文件的大小應在建議的300MB-700MB範圍內。 如果段文件大於此範圍,則應考慮更改時間間隔的粒度或對數據進行分區,並在partitionsSpec中調整targetPartitionSize(此參數的最佳起點是500萬行)。

段的核心數據結構:

在這裡,我們描述了段文件的內部結構,該結構基本上是柱狀的:每列的數據都佈置在單獨的數據結構中。 通過分別存儲每列,Druid可以通過僅掃描查詢實際需要的那些列來減少查詢延遲。

共有三種基本列類型:時間戳列,維度列和指標列,如下圖所示:

timestamp和metric列很簡單:在幕後每個都是由LZ4壓縮的整數或浮點值的數組。 一旦查詢知道需要選擇的行,它就簡單地解壓縮這些行,取出相關的行,然後應用所需的聚合運算符。 與所有列一樣,如果查詢不需要一列,則該列的數據將被跳過。

Apache Druid —當代大數據分析的必要條件

> Data-Structure of the implementation strategy behind a Druid Segment

維度列有所不同,因為它們支持篩選和分組操作,因此每個維度都需要以下三個數據結構:

· 將值(始終被視為字符串)映射到整數ID的字典,

· 列值的列表,使用1中的字典進行編碼,以及

· 對於列中的每個不同值,一個位圖指示哪些行包含該值。

為什麼要使用這三個數據結構? 字典僅將字符串值映射為整數id,以便可以緊湊地表示(2)和(3)中的值。 (3)中的位圖(也稱為反向索引)允許進行快速過濾操作(特別是,位圖對於快速應用AND和OR運算符非常方便)。 最後,group by和TopN查詢需要(2)中的值列表。 換句話說,僅基於過濾器彙總指標的查詢不需要觸摸存儲在(2)中的維度值列表。

Druid集群設置:

Apache Druid旨在作為可伸縮的容錯群集進行部署。 Druid進程可以按照我們喜歡的任何方式進行部署,但是為了易於部署,我們建議將其組織為三種服務器類型:主服務器,查詢服務器和數據服務器。

· 主機:運行協調器和霸主流程,管理數據可用性和接收。

· 查詢:運行代理和可選的路由器進程,處理來自外部客戶端的查詢。

· 數據:運行Historical和MiddleManager進程,執行提取工作負載並存儲所有可查詢的數據。

Druid架構:

Druid有基於微服務的架構,可以認為是一個反彙編的數據庫。 Druid中的每個核心服務(攝取,查詢和協調)都可以單獨或聯合部署在商用硬件上。

Apache Druid —當代大數據分析的必要條件

Apache Druid是一個實時分析數據庫,旨在對大型數據集進行快速切片和切分分析(" OLAP"查詢)。 Druid最常用作數據庫,以支持對實時攝取,快速查詢性能和高正常運行時間很重要的用例。 因此,Druid通常用於為分析應用程序的GUI供電,或用作需要快速聚合的高併發API的後端。 德魯伊最適合面向事件的數據。

德魯伊的常見應用領域包括:

  • · 點擊流分析(網絡和移動分析)
  • · 網絡遙測分析(網絡性能監控)
  • · 服務器指標存儲
  • · 供應鏈分析(製造指標)
  • · 應用程序性能指標
  • · 數字營銷/廣告分析
  • · 商業智能/ OLAP

Druid最適合的用例:

如果我們的用例適合以下幾個描述符,則Druid可能是一個不錯的選擇:

  • · 插入率很高,但更新並不常見。
  • · 我們大多數查詢是聚合查詢和報告查詢("分組依據"查詢)。 我們可能還會搜索和掃描查詢。
  • · 我們將查詢等待時間定為100毫秒到幾秒鐘。
  • · 我們的數據具有時間成分(Druid包括與時間特別相關的優化和設計選擇)。
  • · 我們可能有多個表,但是每個查詢僅命中一個大的分佈式表。 查詢可能會擊中多個較小的"查找"表。
  • · 我們具有高基數數據列(例如URL,用戶ID),並且需要對其進行快速計數和排名。
  • · 我們要從Kafka,HDFS,平面文件或對象存儲(如Amazon S3)加載數據。

參考文獻:

Apache Druid已有關於其體系結構和工作原理的非常詳盡的文檔。 我在將Druid用作我當前組織的數據平臺中的三個分析產品團隊的骨幹方面有經驗。 根據我的經驗和需求,我試圖記下上述博客中的所有相關詳細信息。

(本文翻譯自Ronik Basak的文章《Apache Druid — The sine qua non of contemporary Big-Data analytics》,參考:https://medium.com/swlh/apache-druid-the-sine-qua-non-of-contemporary-big-data-analytics-cc82a081e)


分享到:


相關文章: