http://samza.incubator.apache.org/learn/documentation/0.7.0/introduction/architecture.html
Samza由三層組成:
- A streaming layer 訊息流層
- An execution layer 執行層
- A processing layer 處理層
Samza自身提供了對所有三個層的支援:
- Streaming : Kafka
- Execution: YARN
- Processing: Samza API
這三個部分組裝到一起構成了Samza:
這個架構遵循了Hadoop的類似模式(使用YARN做為執行層,HDFS做儲存,MapReduce做處理層API)
在對這三層的每一層做深入介紹之前,首先要說明下:Samza不僅支援Kafka和YARN。Samza的執行層和訊息流層都是pluggable的,並且如果使用者喜歡,可以自己實現。
Kafka
Kafka是一個分散式的釋出-訂閱以及訊息佇列系統,提供了at least once的訊息保證(也就是說這個系統保證了沒有訊息會丟失,但是在特定的錯誤情境下,一個consumer可能會收到多於一次的同一條訊息),並且高可用的partition(也就是說一個stream的partition即使在機器down掉的情下仍然可用)。
在kafka,每一個流被稱為一個topic。每個topic被分割槽以備份到多個機器上,這些機器叫broker。當一個producer傳送一條訊息到一個topic,這個producer提供一個key,來決定這個訊息應該被送往topic的哪個partition。Kafka broker接收訊息,並且儲存訊息。Kafka consumer可以通過訂閱 這個topic的所有partition來讀取這個topic(譯註:Kafka consumer可以計閱特定的partition,但是要獲取一個topic的所有訊息,就得訂閱這個topic的所有partition)。
Kafka有一些有趣的屬性:
- 發給一個topic的有相同key的訊息都被髮送往同一個partition。這意味著,如果你想要讀關於某個user ID的所有訊息,只需要讀包括這個user ID的的那個partition,而不是整個topic(假設user ID被當作key)
- 一個partition是一個訊息序列,其順序為訊息到達的順序,所有你可以使用一個單調遞增的offset(就像陣列的索引一樣)來引用partition裡的訊息。這意味著broker不用追蹤哪個訊息被哪個consumer消費過——consumer可以自己記錄消費的狀態,它只要記錄下它消費的最後一條訊息的offset就行。(譯註:設想如果訊息沒有offset,當消費者重啟時,它該怎麼知道自己上次消費到哪了。offset使得伺服器端不需要記錄消費者的狀態,這個狀態消費者可以自己維護)。消費者就知道所有offset小於當前offset的消費都已經被處理了;所有offset更大的訊息都還沒有被處理。
更詳細的資訊,請看kafka的文件。
YARN
YARN(Yet Another Resource Negotiator)是Hadoop的下一代叢集排程器。它允許你分派一定數目的 container(程式)到一個叢集中,並且在container中執行任意的指令。
當一個應用程式與YARN互動時,看起來就像這樣:
- 應用程式: 我想要在兩臺512M記憶體的機器上執行指令X
- YARN: 酷, 你的程式碼哪呢?
- 應用程式: http://path.to.host/jobs/download/my.tgz
- YARN:我現在在node-1.grid和node-2.grid上跑你的程式啦
Samza使用YARN來管理其部署、容錯、日誌記錄、資源隔離、安全,以及本地化。下面有一個對YARN的簡介;這篇Hortonworks的文章做了一個更好的概述。
YARN的架構
YARN有三個重要的部分:一個資源管理器ResourceManager、一個NodeManager、一個ApplicationMaster。在一個YARN grid中,每個機器執行著一個NodeManager,NodeManager負責在這臺機器上啟動程式。ResourceManager告訴所有NodeManager它們應該執行什麼。當應用程式想要在叢集上執行的時候,它會與ResourceManager來對話。第三個部分,ApplicationMaster,實際上是一段應用程式指定的執行在YARN叢集上的程式碼,它負責管理應用程式的工作負荷,請求獲取container(通常是UNIX程式),以及當container出現故障時處理通知。
Samza 和 YARN
Samza提供了一個YARN ApplicationMaster和一個自帶的YARN job。Samza和YARN的整合用下面的圖列出(不同的顏色表示不同的主機)
當Samza client啟動一個Samza job時,它與YARN RM進行通訊。YARN RN告訴一個YARN NM來在叢集上給Samza的ApplicationMaster分配空間。當NM分配好空間以後,它啟動Samza AM。當Samza AM啟動後,它向YARN RM請求一個或更多的 YARN container來執行Samza TaskRunner。然後,RM和NM一起工作,來為containers安排空間。當空間被分配好了,NM啟動Samza containers.
Samza
Samza使用YARN和Kafka來提供一個框架,用於多級流處理和分割槽stage-wise stream processing and partitioning。所有東西在一起,看來就樣(用不同的顏色表示不同的主機)
Samza client使用YARN來執行Samza任務。Samza TaskRunners執行在一個或更多的YARN containers,並且執行使用者輸入的Samza StreamTasks. Samza Stream Task的輸入和輸出都來自Kafka brokers,這些brokers通常和YARN NMs座落在同樣的一些機器上。
例子
讓我們來看一下真正的例子:假如我們想要計算頁面點選量的總數。使用SQL時,你可能會這麼寫:
SELECT user_id, COUNT(*) FROM PageViewEvent GROUP BY user_id.
雖然Samza現在不支援SQL,但是思想是一致的。這個查詢需機兩個job:一個將訊息按user ID分組,另一個來做計數。
在第一個job裡,把有相同user ID的訊息傳送到一箇中間topic的相同partition裡,以此來完成分組。為了做到這些,你可以在第一個job裡用user ID做為訊息的key,這key被對映到中間topic的一個partition(通過對key做雜湊,然後對partition數量求模)。第二個job消費中間的topic。第二個job中的每個task,消費中間topic的一個partition,也就是所有user ID的一個子集對應的所有訊息。Task對於分配給它的partition裡的每一個使用者id有一個計數器,每當這個task收到一個訊息時,它就會更新這個訊息中的user ID對應的計數器。
如果你熟悉Hadoop,你可能把這個認為是一個Map/Reduce操作,在mapper中,每條記錄和一個特定的key關聯,有相同key的記錄被這個框架組織到一起,然後在reducer中進行計數。Hadoop和Samza的不同在於Hadoop操作於確定的輸入,而Samza工作於無界的資料流。
kafka接受第一個job傳送的訊息,並把它們快取在磁碟,分佈在多個機器中。這樣來幫助這個系統的容錯:如果機器故障了,沒有訊息會丟失,因為它們被複制到了其它機器上。如果第二個job工作很慢或者因為某些原因停止消費訊息,第一個job也不會受影響:磁碟快取會吸收第一個job積壓的訊息直到第二個job追趕上來。
通過topic分割槽,以及把一個流處理分成在多個機器上執行的job和並行的task,Samza可以擴充套件到可以流處理非常高的訊息吞吐量,通過使用YARN和Kafka,Samza實現容錯:如果一個處理或者機器down了,它會自動在另一個機器上重啟,並且從上次停下來的點繼處理。
下一節:對比介紹