之前在《 》中我們分析了服務器端的可靠性和一致性的配置。即使在服務器端做了很強的一致性配置,也不能保證不丟消息。假如在Broker那邊的配置是:
<code>replication.factor
=3
// 有1
個主節點,2
個從節點min.insync.replicas
=2
// 要保證2
個同步的節點unclean.leader.election.enable
=false
// 不允許out-of-sync的節點當選lead/<code>
我們來看看生產者producer的哪些配置也會影響可靠性。
確認成功 acks
"acks",需要多少從節點確認收到時,才認為成功送達消息。有三個選項:
- acks=0,那麼客戶端只要把消息發出去,不等broker的響應就認為發送成功了。如果是客戶端本地的網卡有問題,或者序列化失敗,那麼客戶端會有異常拋出。否則就認為成功。萬一在客戶端這邊剛發到broker那邊,broker就掛了。客戶端是不知道的。這樣客戶端就認為丟消息了。
- acks=1,那麼broker的主分區節點只要收到消息就會返回給客戶端成功消息。如果剛返回,還沒有來得及複製到從節點去,主節點就掛了,那麼客戶端以為成功了,其實這個消息也丟了。
- acks=all,那麼客戶端如果得到broker的成功消息,就代表broker已經提交(commit)了消息,除了主節點,另外的一個或者兩個從節點都複製好了。這時候就算lead掛了,也還有一個從節點包含這個消息。這是最安全的配置,同時也是最慢的配置。
重發次數 retries
任何外部的IO都需要考慮retry,因為任何外部服務都有可能臨時不可用。broker有可能在換主,有可能臨時連不上,這個時候客戶端最安全的是無限的從發。直到broker恢復正常。默認的值是2147483647。
這個是producer客戶端內部的實現。但是,只有broker返回的是可重試(retriable)的錯誤時(比如換主是返回LEADER_NOT_AVAILABLE),producer才會自動重發。如果是不可重試(nonretriable)的錯誤(比如INVALID_CONFIG),那麼客戶端再怎麼重試也沒用。
需要客戶端處理的錯誤
- 發送之前就出錯,比如序列化失敗,客戶端需要自己處理。
- 如果可以重試的錯誤kafka producer會處理。但是對於不可重試(nonretriable)的錯誤,就需要客戶端來處理。
- 如果客戶端設置的retries比較小(比如10),那麼客戶端需要自己處理重試10次以後還不成功的情況。
下次我們繼續看在消費者那邊有哪些配置會影響一致性的保證。