Producer在發佈消息到某個Partition時,先通過ZooKeeper找到該Partition的Leader,然後無論該Topic的Replication Factor爲多少(也即該Partition有多少個Replica),Producer只將該消息發送到該Partition的Leader。Leader會將該消息寫入其本地Log。每個Follower都從Leader中pull數據。
生產者丟數據
在kafka生產中,基本都有一個leader和多個follwer。follwer會去同步leader的信息。因此,爲了避免生產者丟數據,做如下兩點配置
-
第一個配置要在producer端設置acks=all。這個配置保證了,follwer同步完成後,才認爲消息發送成功。
-
在producer端設置retries=MAX,一旦寫入失敗,這無限重試
消息隊列丟數據
針對消息隊列丟數據的情況,無外乎就是,數據還沒同步,leader就掛了,這時zookpeer會將其他的follwer切換爲leader,那數據就丟失了。針對這種情況,應該做兩個配置。
-
replication.factor參數,這個值必須大於1,即要求每個partition必須有至少2個副本。
-
min.insync.replicas參數,這個值必須大於1,這個是要求一個leader至少感知到有至少一個follower還跟自己保持聯繫這兩個配置加上上面生產者的配置聯合起來用,基本可確保kafka不丟數據
消費者丟數據
這種情況一般是自動提交了offset,然後你處理程序過程中掛了。kafka以爲你處理好了。再強調一次offset是幹嘛的。
offset:指的是kafka的topic中的每個消費組消費的下標。簡單的來說就是一條消息對應一個offset下標,每次消費數據的時候如果提交offset,那麼下次消費就會從提交的offset加一那裏開始消費。
比如一個topic中有100條數據,我消費了50條並且提交了,那麼此時的kafka服務端記錄提交的offset就是49(offset從0開始),那麼下次消費的時候offset就從50開始消費。
如何保證消息的順序性
針對這個問題,通過某種算法,將需要保持先後順序的消息放到同一個消息隊列中(kafka中就是partition,rabbitMq中就是queue)。然後只用一個消費者去消費該隊列。
有的人會問:那如果爲了吞吐量,有多個消費者去消費怎麼辦?
簡單來說消息的時序性也可以通過錯誤重試來解決。
比如我們有一個微博的操作,發微博、寫評論、刪除微博,這三個異步操作。如果是這樣一個業務場景,那隻要重試就行。比如你一個消費者先執行了寫評論的操作,但是這時候,微博都還沒發,寫評論一定是失敗的,等一段時間。等另一個消費者,先執行寫評論的操作後,再執行,就可以成功。
總之,針對這個問題,我的觀點是保證入隊有序就行,出隊以後的順序交給消費者自己去保證,沒有固定套路。