topic:生產組:P0\P1----P14
一個消費組:c0 c1 c2
依據Consumer的負載均衡分配
消費順序「c0:p0-p4 c1:p5-p9 c2:p10-p14
問題:忽然發現讀offset 堆積太多 增長消費者也沒用
緣由: C2節點物理故障,會把數據分給C0和C1,而後C2恢復(生產上會用相似superviser重新啓動掛掉的進程),再從新分配數據,這樣來來回回浪費了不少時間 每次挪回都從新洗牌,新版本已經修復此問題,因此不該該隨便恢復進程
解決:應該預分配節點,比正常的多一些,這樣掛點一兩個也沒有太大影響服務器
消息系統負責將數據從一個應用程序傳輸到另外一個應用程序
點對點消息系統和發佈 - 訂閱消息系統架構
Kafka專爲分佈式高吞吐量系統而設計。 與其餘消息傳遞系統相比,Kafka具備更好的吞吐量,內置分區,複製和固有的容錯能力,這使得它很是適合大規模消息處理應用程序。併發
數據存儲在主題中。Topic至關於Queue。
主題被拆分紅分區。 每一個這樣的分區包含不可變有序序列的消息。分區被實現爲具備相等大小的一組分段文件。任何發佈到此partition的消息都會被直接追加到log文件的尾部,每條消息在文件中的位置稱爲offset(偏移量),offset爲一個long型數字,它是惟一標記一條消息。它惟一的標記一條消息。kafka並無提供其餘額外的索引機制來存儲offset,由於在kafka中幾乎不容許對消息進行「隨機讀寫」。負載均衡
每一個分區消息具備稱爲 offset 的惟一序列標識。dom
副本只是一個分區的備份。 副本從不讀取或寫入數據。 它們用於防止數據丟失。異步
代理是負責維護髮布數據的簡單系統。 每一個代理能夠每一個主題具備零個或多個分區。
每個kafka實例(或者說每臺kafka服務器節點)就是一個broker,一個broker能夠有多個topicsocket
Kafka有多個代理被稱爲Kafka集羣。 能夠擴展Kafka集羣,無需停機。 這些集羣用於管理消息數據的持久性和複製。分佈式
每當生產者將消息發佈給代理時,代理只需將消息附加到最後一個段文件。實際上,該消息將被附加到分區。 生產者還能夠向他們選擇的分區發送消息。ui
Consumers從broker處讀取數據。 消費者訂閱一個或多個主題,並經過從代理中提取數據來使用已發佈的消息。設計
Consumer本身維護消費到哪一個offet
offet的存放位子依據消費類型的不一樣,若是JAVA API 消費則是存放在zookeeper,若是是kafka默認自帶的消費則是存放在kafka自帶的topic【__consumer_offsets】
每一個Consumer都有對應的group
group是==queue消費模型==:==各個Consumer消費不一樣的partition,所以一個消息在group內只消費一次==
group是==publish-subscribe消費模型==:各個group各自獨立消費,互不影響,所以一個消息被每一個group消費一次。
這是kafka用來實現一個topic消息的廣播(發給全部的consumer)和單播(發給任意一個consumer)的手段。
kafka只支持Topic
每一個group中能夠有多個consumer,每一個consumer屬於一個consumer group; 一般狀況下,一個group中會包含多個consumer,這樣不只能夠==提升topic中消息的併發消費能力,並且還能提升"故障容錯"性==,若是group中的某個consumer失效那麼其消費的partitions將會有其餘consumer自動接管。
總結:
==一個group中的consumer只會消費一個topic的一條消息,每一個consumer消費不一樣的partition。==
在kafka中,一個partition中的消息只會被group中的一個consumer消費(同一時刻);
一個Topic中的每一個partions,只會被一個"訂閱者"中的一個consumer消費,不過一個consumer能夠同時消費多個partitions中的消息。
kafka的設計原理決定,對於一個topic,同一個group中不能有多於partitions個數的consumer同時消費,不然將意味着某些consumer將沒法獲得消息。==可是在設計的時候我的以爲能夠多些consumer 已解決前面遇到的坑。==
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
當一個group中,有consumer加入或者離開時,會觸發partitions均衡.均衡的最終目的,是提高topic的併發消費能力,步驟以下:
因爲Producer和Consumer都只會與Leader角色的分區副本相連,因此kafka須要以集羣的組織形式提供主題下的消息高可用。kafka支持主備複製,因此消息具有高可用和持久性。
一個分區能夠有多個副本,這些副本保存在不一樣的broker上。每一個分區的副本中都會有一個做爲Leader。當一個broker失敗時,Leader在這臺broker上的分區都會變得不可用,kafka會自動移除Leader,再其餘副本中選一個做爲新的Leader。
kafka維護了一個同步狀態的副本集合(a set of In-Sync Replicas),簡稱ISR,集合中的節是和leader保持高度一致,任何一條消息只有被這個集合中的每一個節點讀取並追加到日誌中,纔會向外部通知說「這個消息已經被提交」。
只有當消息被全部的副本加入到日誌中時,纔算是「committed」,只有committed的消息纔會發送給consumer,這樣就不用擔憂一旦leader down掉了消息會丟失。
消息從leader複製到follower, 咱們能夠經過決定Producer是否等待消息被提交的通知(ack)來區分同步複製和異步複製。
異步複製流程:和同步複製的區別在於,leader寫入本地log以後,直接向client回傳ack消息,不須要等待全部follower複製完成。
kafka支持副本模式,那麼其中一個Broker裏的掛掉,一個新的leader就能經過ISR機制推選出來,繼續處理讀寫請求。
在項目啓動之初來預測未來項目會碰到什麼需求,是極其困難的。消息隊列在處理過程當中間插入了一個隱含的、基於數據的接口層,兩邊的處理過程都要實現這一接口。
有時在處理數據的時候處理過程會失敗。除非數據被持久化,不然將永遠丟失。對於傳統的message queue而言,通常會刪除已經被消費的消息,而Kafka集羣會保留全部的消息,不管其被消費與否
由於消息隊列解耦了你的處理過程,因此增大消息入隊和處理的頻率是很容易的;只要另外增長處理過程便可。
使用消息隊列可以使關鍵組件頂住增加的訪問壓力,而不是由於超出負荷的請求而徹底崩潰。
當體系的一部分組件失效,不會影響到整個系統。
獲取一個消息只是」預約」了這個消息,暫時把它移出了隊列。除非客戶端明確的表示已經處理完了這個消息,不然這個消息會被放回隊列中去,在一段可配置的時間以後可再次被處理。
在許多狀況下,數據處理的順序都很重要。消息隊列原本就是排序的,而且能保證數據會按照特定的順序來處理。
在任何重要的系統中,都會有須要不一樣的處理時間的元素。
。消息隊列提供了異步處理機制,容許你把一個消息放入隊列,但並不當即處理它。你想向隊列中放入多少消息就放多少,而後在你樂意的時候再去處理它們。