Apache Druid 中文翻譯 - 設計(Design)

設計

德魯伊具有多進程、分佈式的架構,並且在設計爲雲友好且易操作的系統。每種Druid進程類型(指Druid框架之中的各種組件)都可以獨立配置和水平擴展,從而爲您的集羣提供最大的靈活性。這種設計還提高了容錯能力:一個組件的故障不會立即影響其他組件。

進程和服務器

Druid有幾種進程類型,簡述如下:

  • Coordinator 協調器進程管理羣集上的數據可用性。
  • Overlord 統治進程控制數據攝入工作負載的分配。
  • Broker 代理進程處理來自外部客戶端的查詢。
  • Router 路由進程是可選進程,可以將請求路由到代理,協調器和霸主。
  • Historical 歷史進程存儲可查詢的數據。
  • MiddleManager 中間管理進程負責攝取數據。

Druid進程可以按照您喜歡的任何方式進行部署,但是爲了便於部署,我們建議將其組織爲三種服務器類型:主服務器,查詢服務器和數據服務器。

  • Master:運行協調器和統治流程,管理數據可用性和接收。
  • Query:運行代理和可選的路由器進程,處理來自外部客戶端的查詢。
  • Data:運行Historical和MiddleManager進程,執行提取工作負載並存儲所有可查詢的數據。

有關進程和服務器架構的更多詳細信息,請參閱Druid進程和服務器

外部依賴

除了內置的進程類型外,Druid還具有三個外部依賴項。這些外部依賴項能夠利用現有的基礎結構。

Deep storage 深度儲存

每個Druid服務器均可訪問共享文件存儲。在集羣部署中,這通常將是分佈式對象存儲(例如S3或HDFS)或通過網絡掛載的文件系統。在單服務器部署中,這通常是本地磁盤。Druid使用deep storage來存儲已攝取到系統中的所有數據。

Druid僅將deep storage用作數據的備份,並作爲在Druid進程之間在後臺傳輸數據的方式(注:多個Druid實例可以通過Deep Storage 共享數據)。處理查詢請求的時候,歷史進程不會從深度存儲中讀取數據,而是會在提供任何查詢之前從其本地磁盤讀取預攝入的segments 。這意味着Druid不需要在查詢期間訪問deep storage,從而幫助它提供最短的查詢延遲。這也意味着在deep storage和 Historical進程中,必須有足夠的磁盤空間用於加載你計劃攝取的數據。

深度存儲是Druid的彈性,容錯設計的重要組成部分。即使每臺數據服務器都丟失並重新配置,Druid也可以從深度存儲中引導。

有關更多詳細信息,請參閱深度存儲頁面。

Metadata storage 元數據存儲

Metadata storage區包含各種共享的系統元數據,例如segment 可用性信息和task信息。在集羣部署中,這通常將是傳統的RDBMS,例如PostgreSQL或MySQL。在單服務器部署中,它通常將是本地存儲的Apache Derby數據庫。

有關更多詳細信息,請參見“ 元數據存儲”頁面。

ZooKeeper

用於內部服務發現,協調和leader選舉。

有關更多詳細信息,請參見ZooKeeper頁面。

Architecture diagram 架構圖

下圖顯示了使用建議的Master / Query / Data服務器組織的查詢和數據在整個體系結構中的流動方式:

 

存儲設計

Datasources 數據源segments段

Druid數據存儲在“Datasources”中,類似於傳統RDBMS中的表。每個數據源都按時間分區,並且可以選擇按其他屬性進一步分區。每個時間範圍都稱爲“chunk”(例如,如果您的數據源按天劃分,則爲一天)。在一個chunk內,數據被劃分爲一個或多個 segments。每個segments都是單個文件,通常包含多達幾百萬行的數據。由於segments是按時間塊組織的,因此將細分視爲生活在時間線上的以下內容有時會有所幫助:

 

 

一個Datasources 可能具有從幾個段到數十萬甚至數百萬個segments。每個segments都是從在MiddleManager上創建開始的,在那個時候,segments是可變的且未提交的。爲了生成緊湊且支持快速查詢的數據文件,segments構建過程包括以下步驟,:

  • 轉換爲列格式
  • 使用位圖索引編制索引
  • 使用各種算法進行壓縮
    • 字符串列的ID存儲最小化的字典編碼
    • 位圖索引的位圖壓縮
    • 所有列的類型感知壓縮

segments會定期提交和發佈。發佈後,它們被寫入Deep storage ,變得不可變,並從MiddleManagers遷移到Historical處理。有關該segment的Entry也將寫入到元數據存儲中。Entry是有關該segment的元數據的自描述位,包括諸如segment的模式,其大小以及其在Deep storage上的位置之類的信息。這些條目是Coordinator用來了解集羣上應該有哪些數據的內容。

有關segments文件格式的詳細信息,請參閱段文件

有關在Druid中對數據建模的詳細信息,請參見模式設計

Indexing 索引 和handoff移交

索引 是創建新段的機制,移交是它們被髮布並開始由Historical進程提供服務的機制。該機制在索引端的工作方式如下:

  1. 一個索引任務開始運行,並建立一個新的segments。它必須在開始構建段之前確定該段的標識符。對於要追加的任務(例如Kafka任務,或追加(append)模式中的索引任務),可以通過在Overlord上調用“allocate” API來完成,以潛在地將新分區(partition )添加到現有的段集中。對於要覆蓋(overwriting )的任務(例如Hadoop任務或不在追加模式下的索引任務),這可以通過鎖定間隔(注:覆蓋的時間段)並創建新的版本號和新的段集來完成。
  2. 如果索引任務是實時任務(例如Kafka任務),則此時可以立即查詢該段。它可用,但尚未發佈。
  3. 索引任務完成對段的數據讀取後,會將其推入深度存儲,然後通過將記錄寫入元數據存儲來發布它。
  4. 如果索引任務是實時任務,則此時它等待“Historical”進程加載該段。如果索引任務不是實時任務,它將立即退出。

在Coordinator / Historical端,看起來像這樣:

  1. Coordinator 定期(默認情況下,每1分鐘)輪詢元數據存儲區以查找新發布的段。
  2. 當Coordinator 找到已發佈和使用但不可用的段時,它會選擇一個“Historical”進程並指示“Historical”來加載該段
  3. 歷史記錄會加載段並開始處理。
  4. 此時,如果索引任務正在等待切換,它將退出。

Segment identifiers 段標識符

段均具有包含以下部分的四部分標識符:

  • 數據源名稱。
  • 時間間隔(對於包含分段的時間塊;這對應segmentGranularity於攝取時指定的時間間隔)。
  • 版本號(通常爲ISO8601時間戳,與首次啓動段集的時間相對應)。
  • 分區號(整數,在數據源+間隔+版本內是唯一的;可能不一定是連續的)。

例如,這是datasource clarity-cloud0,time chunk 2018-05-21T16:00:00.000Z/2018-05-21T17:00:00.000Z,version 2018-05-21T15:56:09.909Z和分區號1中的段的標識符:

clarity-cloud0_2018-05-21T16:00:00.000Z_2018-05-21T17:00:00.000Z_2018-05-21T15:56:09.909Z_1
複製

分區號爲0(塊中的第一個分區)的段省略了分區號,如以下示例所示,它是與上一個分區在同一時間塊中的段,但分區號爲0而不是1:

clarity-cloud0_2018-05-21T16:00:00.000Z_2018-05-21T17:00:00.000Z_2018-05-21T15:56:09.909Z
複製

段版本控制

您可能想知道上一節中描述的“版本號”是做什麼的。或者,您可能不是,在這種情況下您可以跳過本部分!

段版本控制是爲了支持批處理模式覆蓋。在Druid中,如果您要做的只是追加(append)數據,那麼每個時間塊只有一個版本。但是,當您覆蓋數據時,在幕後發生的事情是使用相同的數據源,相同的時間間隔,但版本號更高的方式創建了一組新的段。這向Druid系統的其餘部分發出信號,表明應從集羣中刪除較舊的版本,而應使用新版本替換它。

對於用戶而言,切換似乎是瞬間發生的,因爲Druid通過首先加載新數據(但不允許對其進行查詢)來處理此問題,然後在所有新數據加載完畢後,立即切換所有新查詢以使用這些新段。然後,它會在幾分鐘後刪除舊段。

段生命週期

每個部分的生命週期都涉及以下三個主要領域:

  1. 元數據存儲區:一旦構建完段,就將段元數據(一個小的JSON有效負載(payload ),通常不超過幾個KB)存儲在 元數據存儲區中。將段的記錄插入元數據存儲的操作稱爲發佈。這些元數據記錄具有一個名爲used的布爾標誌,用於控制該段是否可查詢。由實時任務創建的段將在發佈之前可用(available),因爲它們僅在段完成時才發佈,並且不接受任何其他數據行。
  2. 深度存儲:分段數據構建完成後,會將分段數據文件推送到深度存儲。這在將元數據發佈到元數據存儲之前立即發生。
  3. 查詢的可用性:段可用於在某些Druid數據服務器上進行查詢,例如實時任務或歷史進程。

您可以使用Druid SQL sys.segments檢查當前活動段的狀態 。它包括以下標誌:

  • is_published:如果段元數據已發佈到存儲的元數據中,used爲true。
  • is_available:如果該段當前可用於實時任務或歷史流程查詢,則爲True。
  • is_realtime:如果分段在實時任務上可用,則爲true 。對於使用實時提取的數據源,通常會先開始true,然後false隨着段的發佈和移交而變成。
  • is_overshadowed:如果該段已發佈(used設置爲true)並且被其他已發佈的段完全遮蓋,則爲true。通常,這是一個過渡狀態,處於此狀態的段很快就會將其used標誌自動設置爲false。

查詢處理

查詢首先進入Broker,Broker將在其中識別哪些段具有與該查詢有關的數據。段列表始終按時間篩選,也可以根據其他屬性來篩選,這取決於數據源的分區方式。然後,Broker將確定哪些Historical 和 MiddleManager爲這些段提供服務,並將重寫的子查詢發送給每個進程。Historical / MiddleManager進程將接受查詢,對其進行處理並返回結果。Broker接收結果並將它們合併在一起以得到最終響應,並將其返回給原始調用方。

Broker篩選是Druid限制每個查詢必須掃描的數據量的一種重要方法,但這不是唯一的方法。對於比Broker可以使用的過濾器更細粒度的過濾器,每個段內的索引結構允許Druid在查看任何數據行之前先找出哪些行(如果有)與過濾器集匹配。一旦Druid知道哪些行與特定查詢匹配,它就只會訪問該查詢所需的特定列。在這些列中,Druid可以在行與行之間跳過,從而避免讀取與查詢過濾器不匹配的數據。

因此,Druid使用三種不同的技術來最大化查詢性能:

  • 篩選每個查詢所需要訪問的段。
  • 在每個段中,使用索引來標識必須訪問的行。
  • 在每個段中,僅讀取與特定查詢相關的特定行和列。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章