1. 程式人生 > >I want to know a little more.

I want to know a little more.

序:如何保證kafka全域性訊息有序?

  比如,有100條有序資料,生產者傳送到kafka叢集,kafka的分片有4個,可能的情況就是一個分片儲存0-25,一個儲存25-50......這樣訊息在kafka中儲存是區域性有序了。嚴格說,kafka是無法保證全域性訊息有序的,沒有這個機制,只能區域性有序。

1、Kafka是什麼-intsmaze

  在流式計算中,Kafka一般用來快取資料,Storm通過消費Kafka的資料進行計算。

  Apache Kafka是一個開源訊息系統,由Scala寫成。

  Kafka是一個分散式訊息佇列:生產者、消費者的功能。它提供了類似於JMS的特性,但是在設計實現上完全不同,此外它並不是JMS規範的實現。

  Kafka對訊息儲存時根據Topic進行歸類,傳送訊息者稱為Producer,訊息接受者稱為Consumer,此外kafka叢集由多個kafka例項組成,每個例項(server)稱為broker。

  題外話:無論是kafka叢集,還是producer和consumer都依賴於zookeeper叢集儲存一些meta資訊,來保證系統可用性。

2、Kafka核心元件-intsmaze

  Topic:訊息根據Topic進行歸類,可以理解為一個隊裡。

  Producer:訊息生產者,就是向kafka broker發訊息的客戶端。

  Consumer:訊息消費者,向kafka broker取訊息的客戶端。

  broker:每個kafka例項(server),一臺kafka伺服器就是一個broker,一個叢集由多個broker組成,一個broker可以容納多個topic。

  Zookeeper:依賴叢集儲存meta資訊。

3、Kafka訊息有序性-intsmaze

生產者是一個獨立的叢集,和kafka的broker叢集,消費者叢集沒有太直接的干係。比如flume就可以作為生產者,內部呼叫kafka的客戶端程式碼,確保把收集的資料發到kafka叢集中。

  如何保證kafka全域性訊息有序?

  比如,有100條有序資料,生產者傳送到kafka叢集,kafka的分片有4個,可能的情況就是一個分片儲存0-25,一個儲存25-50......這樣訊息在kafka中儲存是區域性有序了。嚴格說,kafka是無法保證全域性訊息有序的,沒有這個機制,只能區域性有序。

  但是如果只有一個分片和一個訊息的生產者,那麼就相當於訊息全域性有序了。如果有多個訊息生產者,就算只有一個分片,如果這些生產者的訊息都發給這個分片,那kafka中的訊息連區域性有序都沒有辦法了。

4、消費者組-intsmaze

  Consumer Group(CG):這是kafka用來實現一個topic訊息的廣播(發給所有的consumer)和單播(發給任意一個consumer)的手段。一個topic可以有多個CG。topic的訊息會複製(不是真的複製,是概念上的)到所有的CG,但每個partion只會把訊息發給該CG中的一個consumer。如果需要實現廣播,只要每個consumer有一個獨立的CG就可以了。要實現單播只要所有的consumer在同一個CG。用CG還可以將consumer進行自由的分組而不需要多次傳送訊息到不同的topic。

  Partition:為了實現擴充套件性,一個非常大的topic可以分佈到多個broker(即伺服器)上,一個topic可以分為多個partition,每個partition是一個有序的佇列。partition中的每條訊息都會被分配一個有序的id(offset)。kafka只保證按一個partition中的順序將訊息發給consumer,不保證一個topic的整體(多個partition間)的順序。

  Offset:kafka的儲存檔案都是按照offset.kafka來命名,用offset做名字的好處是方便查詢。例如你想找位於2049的位置,只要找到2048.kafka的檔案即可。當然the first offset就是00000000000.kafka。

  每個group中可以有多個consumer,每個consumer屬於一個consumer group;通常情況下,一個group中會包含多個consumer,這樣不僅可以提高topic中訊息的併發消費能力,而且還能提高"故障容錯"性,如果group中的某個consumer失效那麼其消費的partitions將會有其他consumer自動接管。

  對於Topic中的一條特定的訊息,只會被訂閱此Topic的每個group中的其中一個consumer消費,此訊息不會發送給一個group的多個consumer;那麼一個group中所有的consumer將會交錯的消費整個Topic,每個group中consumer訊息消費互相獨立,我們可以認為一個group是一個"訂閱"者。

  在kafka中,一個partition中的訊息只會被group中的一個consumer消費(同一時刻);一個Topic中的每個partions,只會被一個"訂閱者"中的一個consumer消費,不過一個consumer可以同時消費多個partitions中的訊息。

  kafka的設計原理決定,對於一個topic,同一個group中不能有多於partitions個數的consumer同時消費,否則將意味著某些consumer將無法得到訊息。kafka只能保證一個partition中的訊息被某個consumer消費時是順序的;事實上,從Topic角度來說,當有多個partitions時,訊息仍不是全域性有序的。

Producer客戶端負責訊息的分發

  kafka叢集中的任何一個broker都可以向producer提供metadata資訊,這些metadata中包含"叢集中存活的servers列表"/"partitions leader列表"等資訊;

  當producer獲取到metadata資訊之後, producer將會和Topic下所有partition leader保持socket連線

  訊息由producer直接通過socket傳送到broker,中間不會經過任何"路由層",事實上,訊息被路由到哪個partition上由producer客戶端決定;比如可以採用"random""key-hash""輪詢"等,如果一個topic中有多個partitions,那麼在producer端實現"訊息均衡分發"是必要的。

  在producer端的配置檔案中,開發者可以指定partition路由的方式。

  Producer訊息傳送的應答機制設定傳送資料是否需要服務端的反饋,有三個值0,1,-1

    0:producer不會等待broker傳送ack

    1:當leader接收到訊息之後傳送ack

    -1:當所有的follower都同步訊息成功後傳送ack

  request.required.acks=0