首先acks參數,是在kafkaProducer,也就是在生產者客戶端里設置的也就是說,你往kafka寫東西的時候,就可以設置這個參數。
這個參數實際上有三種值可以設置,分別是0,1,和all.
第一種選擇是把參數設置成0
我的kafkaProducer在客戶端,只要把消息發送出去,不管那條數據有沒有在哪怕Partition Leader上落到磁盤,就不管他了,直接認為這個消息發送成功。
如果你采用這種設置的話,那么你必須注意的一點是,可能你發送出去的消息還在半路。結果呢,Partition Leader所在Broker就直接掛了,然后結果你的客戶端還認為消息發送成功了,此時就會導致這條消息就丟失了。
第二種選擇是設置acks=1
只要Partition Leader接收到消息而且寫入本地磁盤了,就認為成功了,不管其他的Follower有沒有同步過去這條消息了。
這種設置其實是kafka默認的設置方式
也就是說默認情況下,要是不設置這個參數,只要Partition Leader寫成功就算成功。
但是這里有一個問題,萬一Partition Leader剛剛接收到消息,Follower還沒來得及同步過去,結果Leader所在的broker宕機了,此時也會導致這條消息丟失,因為人家客戶端已經認為發送成功了。
最后一種情況就是設置為all
Partition Leader接收到消息之后,還必須要求ISR列表里跟Leader保持同步的那些Follower都要把消息同步過去,才能認為這條消息是寫入成功了。
如果說Partition Leader剛接收到了消息,但是結果Follower沒有收到消息,此時Leader宕機了,那么客戶端會感知到這個消息沒發送成功,他會重試再次發送消息過去。
此時可能Partition 2的Follower變成Leader了,此時ISR列表里只有最新的這個Follower轉變成的Leader了,那么只要這個新的Leader接收消息就算成功了。
acks=all就代表數據一定不會丟失了嗎?
當然不是,如果你的Partition只有一個副本,也就是一個Leader,任何Follower都沒有,你認為acks=all有用嗎?
當然沒用了,因為ISR里就一個Leader,他接收完消息后宕機,也會導致數據丟失。
所以說,這個acks=all,必須跟ISR列表里至少有2個以上的副本配合使用,起碼是有一個Leader和一個Follower才可以。
這樣才能保證說寫一條數據過去,一定是2個以上的副本都收到了才算是成功,此時任何一個副本宕機,不會導致數據丟失。