如何將kafka中的資料快速匯入Hadoop?

大資料頻道發表於2018-10-18

Kafka是一個分散式釋出—訂閱系統,由於其強大的分散式和效能特性,迅速成為資料管道的關鍵部分。它可完成許多工作,例如訊息傳遞、指標收集、流處理和日誌聚合。Kafka的另一個有效用途是將資料匯入Hadoop。使用Kafka的關鍵原因是它將資料生產者和消費者分離,允許擁有多個獨立的生產者(可能由不同的開發團隊編寫)。同樣,還有多個獨立的消費者(也可能由不同的團隊編寫)。此外,消費者可以是實時/同步或批次/離線/非同步。當對比RabbitMQ等其他pub-sub工具時,後一個屬性有很大區別。

要使用Kafka,有一些需要理解的概念:

  • topic—topic是相關訊息的訂閱源;

  • 分割槽—每個topic由一個或多個分割槽組成,這些分割槽是由日誌檔案支援的有序訊息佇列;

  • 生產者和消費者—生產者和消費者將訊息寫入分割槽並從分割槽讀取。

  • Brokers—Brokers是管理topic和分割槽併為生產者和消費者請求提供服務的Kafka流程。

Kafka不保證對topic的“完全”排序,只保證組成topic的各個分割槽是有序的。消費者應用程式可以根據需要強制執行對“全域性”topic排序。

圖5.14 顯示了Kafka的概念模型

圖5.15 顯示瞭如何在Kafka部署分發分割槽的示例

為了支援容錯,可以複製topic,這意味著每個分割槽可以在不同主機上具有可配置數量的副本。這提供了更高的容錯能力,這意味著單個伺服器死亡對資料或生產者和消費者的可用性來說不是災難性的。

此處採用Kafka版本0.8和Camus的0.8.X。

實踐:使用Camus將Avro資料從Kafka複製到HDFS

該技巧在已經將資料流入Kafka用於其他目的並且希望將資料置於HDFS中的情況下非常有用。

問題

希望使用Kafka作為資料傳遞機制來將資料匯入HDFS。

解決方案

使用LinkedIn開發的解決方案Camus將Kafka中的資料複製到HDFS。

討論

Camus是LinkedIn開發的一個開源專案。Kafka在LinkedIn大量部署,而Camus則用作將資料從Kafka複製到HDFS。

開箱即用,Camus支援Kafka中的兩種資料格式:JSON和Avro。在這種技術中,我們將透過Camus使用Avro資料。Camus對Avro的內建支援要求Kafka釋出者以專有方式編寫Avro資料,因此對於這種技術,我們假設希望在Kafka中使用vanilla序列化資料。

讓這項技術發揮作用需要完成三個部分的工作:首先要將一些Avro資料寫入Kafka,然後編寫一個簡單的類來幫助Camus反序列化Avro資料,最後執行一個Camus作業來執行資料匯入。

為了把Avro記錄寫入Kafka,在以下程式碼中,需要透過配置必需的Kafka屬性來設定Kafka生成器,從檔案載入一些Avro記錄,並將它們寫出到Kafka:

可以使用以下命令將樣本資料載入到名為test的Kafka的topic中:

Kafka控制檯使用者可用於驗證資料是否已寫入Kafka,這會將二進位制Avro資料轉儲到控制檯:

完成後,編寫一些Camus程式碼,以便可以在Camus中閱讀這些Avro記錄。

實踐:編寫Camus和模式登錄檔

首先,需要了解三種Camus概念:

  • 解碼器—解碼器的工作是將從Kafka提取的原始資料轉換為Camus格式。

  • 編碼器—編碼器將解碼資料序列化為將儲存在HDFS中的格式。

  • Schema登錄檔—提供有關正在編碼的Avro資料的schema資訊。

正如前面提到的,Camus支援Avro資料,但確實需要Kafka生產者使用Camus KafkaAvroMessageEncoder類來編寫資料,該類為Avro序列化二進位制資料新增了部分專有資料,可能是因為Camus中的解碼器可以驗證它是由該類編寫的。

在此示例中,使用 Avro serialization進行序列化,因此需要編寫自己的解碼器。幸運的是,這很簡單:

你可能已經注意到我們在Kafka中寫了一個特定的Avro記錄,但在Camus中我們將該記錄讀作通用的Avro記錄,而不是特定的Avro記錄,這是因為CamusWrapper類僅支援通用Avro記錄。否則,特定的Avro記錄可以更簡單地使用,因為可以使用生成的程式碼並具有隨之而來的所有安全特徵。

CamusWrapper物件是從Kafka提取的資料。此類存在的原因是允許將後設資料貼上到envelope中,例如時間戳,伺服器名稱和服務詳細資訊。強烈建議使用的任何資料都有一些與每條記錄相關的有意義的時間戳(通常這將是建立或生成記錄的時間)。然後,可以使用接受時間戳作為引數的CamusWrapper建構函式:

public CamusWrapper(R record, long timestamp) { ... }

如果未設定時間戳,則Camus將在建立包裝器時建立新的時間戳。在確定輸出記錄的HDFS位置時,在Camus中使用此時間戳和其他後設資料。

接下來,需要編寫一個schema登錄檔,以便Camus Avro編碼器知道正在寫入HDFS的Avro記錄的schema詳細資訊。註冊架構時,還要指定從中拉出Avro記錄的Kafka的topic名稱:

執行Camus

Camus在Hadoop叢集上作為MapReduce作業執行,希望在該叢集中匯入Kafka資料。需要向Camus提供一堆屬性,可以使用命令列或者使用屬性檔案來執行此操作,我們將使用此技術的屬性檔案:

從屬性中可以看出,無需明確告訴Camus要匯入哪些topic。Camus自動與Kafka通訊以發現topic(和分割槽)以及當前的開始和結束偏移。

如果想要精確控制匯入的topic,可以分別使用kafka.whitelist.topics和kafka.blacklist.topics列舉白名單(限制topic)和黑名單(排除topic),可以使用逗號作為分隔符指定多個topic,還支援正規表示式,如以下示例所示,其匹配topic的“topic1”或以“abc”開頭,後跟一個或多個數字的任何topic,可以使用與value完全相同的語法指定黑名單:

kafka.whitelist.topics=topic1,abc[0-9]+

一旦屬性全部設定完畢,就可以執行Camus作業了:

這將導致Avro資料在HDFS中著陸。我們來看看HDFS中的內容:

第一個檔案包含已匯入的資料,其他供Camus管理。

可以使用AvroDump實用程式檢視HDFS中的資料檔案:

那麼,當Camus工作正在執行時究竟發生了什麼? Camus匯入過程作為MapReduce作業執行,如圖5.16所示。

隨著MapReduce中的Camus任務成功,Camus OutputCommitter(允許在任務完成時執行自定義工作的MapReduce構造)以原子方式將任務的資料檔案移動到目標目錄。OutputCommitter還為任務正在處理的所有分割槽建立偏移檔案,同一作業中的其他任務可能會失敗,但這不會影響成功任務的狀態——成功任務的資料和偏移輸出仍然存在,因此後續的Camus執行將從最後一個已知的成功狀態恢復處理。

接下來,讓我們看看Camus匯入資料的位置以及如何控制行為。

資料分割槽

之前,我們看到了Camus匯入位於Kafka的Avro資料,讓我們仔細看看HDFS路徑結構,如圖5.17所示,看看可以做些什麼來確定位置。

圖5.17 在HDFS中解析匯出資料的Camus輸出路徑

路徑的日期/時間由從CamusWrapper中提取的時間戳確定,可以從MessageDecoder中的Kafka記錄中提取時間戳,並將它們提供給CamusWrapper,這將允許按照有意義的日期對資料進行分割槽,而不是預設值,這只是在MapReduce中讀取Kafka記錄的時間。

Camus支援可插拔分割槽程式,允許控制圖5.18所示路徑的一部分。

圖5.18 Camus分割槽路徑

Camus Partitioner介面提供了兩種必須實現的方法:

例如,自定義分割槽程式可建立用於Hive分割槽的路徑。

總結

Camus提供了一個完整的解決方案,可以在HDFS中從Kafka獲取資料,並在出現問題時負責維護狀態和進行錯誤處理。透過將其與Azkaban或Oozie整合,可以輕鬆實現自動化,並根據訊息時間組織HDFS資料執行簡單的資料管理。值得一提的是,當涉及到ETL時,與Flume相比,它的功能是無懈可擊的。

Kafka捆綁了一種將資料匯入HDFS的機制。它有一個KafkaETLInputFormat輸入格式類,可用於在MapReduce作業中從Kafka提取資料。要求編寫MapReduce作業以執行匯入,但優點是可以直接在MapReduce流中使用資料,而不是將HDFS用作資料的中間儲存。接下來,我們將討論如何將駐留在Hadoop中的資料傳輸到其他系統,例如檔案系統和其他地方。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31545816/viewspace-2216076/,如需轉載,請註明出處,否則將追究法律責任。

相關文章