kafka零數據丟失的配置方案


討論一下kafka參數的配置

1、acks 參數配置

acks這個參數有三個值:0,1,-1,但是不用的參數對應的含義不同,那如果我們想要保證數據不丟失,acks 值應該設置為哪個參數呢?

0:代表生產者只要把消息發送出去以后就認為消息發送成功了,這種方式有可能會導致數據丟失,因為有可能消息發送到服務端以后服務端存儲失敗了。

1:代表生產者把消息發送到服務端,服務端的 leader replica 副本寫成功以后,就返回生產者消息發送成功了,這種方式也有可能導致丟數據,因為有可能剛好

數據寫入到leader replica,然后返回處理成功的響應給生產者,假如這個時候leader replica 在的服務器出問題了,follower replica 還沒來得及同步數據,這個時候是會

丟失數據的。

-1(all):代表生產者把消息發送到服務端,服務端的ISR列表里所有的 replica都寫入成功以后,才會返回成功響應給生產者。

假設ISR列表里面有該分區的三個replica(一個leader replica,兩個follower replica ),那么acks=-1 就意味着消息要寫入到 leader replica,並且兩個 follower replica從

leader replica 上同步數據成功,服務端才會給生產者發送消息 發送成功的響應。

所以ISR列表里面的replica 就非常關鍵。如果我們想要保證數據不丟,那么acks的值設置為-1,並且還需要保證ISR列表里面是1個副本以上。

所以 acks的值要設置為-1。

 

2、ISR到底指的是什么東西?

既然大家已經知道了Partition的多副本同步數據的機制了,那么就可以來看看ISR是什么了。

ISR全稱是 "In-Sync Replicas",也就是保持同步的副本,它的含義就是,跟leader 始終保持同步的 follower有哪些。

大家可以想一下,如果說某個follower所在的broker因為JVM Full GC之類的問題,導致自己卡頓了,無法及時從Leader拉取同步數據,那么是不是會導致Follower

數據被Leader要落后很多?

所以這個時候,就意味着follower已經跟leader不再處於同步的關系了。但是只要follower一直及時從leader同步數據,就可以保證他們是處於同步的關系的。

所以每個Partition 都有一個ISR,這個ISR里一定會有Leader自己,因為Leader肯定數據是最新的,然后就是那些跟Leader保持同步的follower,也會在ISR里。

 

3、kafka的存儲機制

 

 由於生產者生產的消息會不斷追加到log文件末尾,為防止log文件過大導致數據定位效率低下,kafka采取了分片和索引機制。

它將每個partition 分為多個 segment,每個segment對應兩個文件:".index"索引文件和 ".log" 數據文件。(一個分區下面有多個log文件,每個log文件大概有1G)

這些文件位於同一文件下,該文件夾的命名規則為 topic 名 - 分區號。

例如:first 這個topic 有三個分區,則其對應的文件夾為 first-0,first-1,first-2。

 

index和log 文件以當前 segment 的第一條消息的 offset命名。下圖為 index文件和log文件的機構示意圖:

 

 .index 文件存儲大量的索引信息, .log文件存儲大量的數據,索引文件中的元數據指向對應數據文件中 Message 的物理偏移量。

 

4、kafka的 zero-copy 零拷貝技術

在kafka中消息存儲模式中,數據存儲在底層文件系統中。當有Consumer訂閱了相應的topic消息,數據需要從磁盤中讀取然后將數據寫回到套接字中(socket)。

此動作看似只需較少的cpu活動,但它的效率非常低。首先內核讀出全盤數據,然后將數據跨越內核用戶推到應用程序,然后應用程序再次跨越內核用戶將數據推回,

寫出到套接字。應用程序實際上在這里擔當了一個不怎么高效的中介角色,將磁盤文件的數據轉入套接字。

數據每遍歷用戶內核一次,就要被拷貝一次,這會消耗CPU周期和內存帶寬。幸運的是,您可以通過一個 零拷貝 的技巧來消除這些拷貝。

使用零拷貝的應用程序要求內核直接將數從磁盤文件拷貝到套接字,而無需通過應用程序。零拷貝不僅大大的提高了應用程序的性能,

而且還減少了內核與用戶模式間的上下文切換。

java 類庫通過 java.nio.channels.FileChannel 中的 transferTo() 方法來在 Linux和Unix系統上支持零拷貝。可以使用transferTo() 方法直接將

字節從它被調用的通道上傳輸到另外一個可寫字節通道上,數據無需流經應用程序。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM