KafKa數據存儲與數據一致性保證 - tianjinsong的專欄 - 博客頻道 - CSDN.NET http://blog.csdn.net/bluetjs/article/details/52986652
數據一致性保證
一致性定義:若某條消息對client可見,那么即使Leader掛了,在新Leader上數據依然可以被讀到
HW-HighWaterMark: client可以從Leader讀到的最大msg offset,即對外可見的最大offset, HW=max(replica.offset)
對于Leader新收到的msg,client不能立刻消費,Leader會等待該消息被所有ISR中的replica同步后,更新HW,此時該消息才能被client消費,這樣就保證了如果Leader fail,該消息仍然可以從新選舉的Leader中獲取。
對于來自內部Broker的讀取請求,沒有HW的限制。同時,Follower也會維護一份自己的HW,Folloer.HW = min(Leader.HW, Follower.offset)
Topic邏輯結構
Topic可分為多個Parition;
Parition內部保證數據的有序,按照消息寫入順序給每個消息賦予一個遞增的offset;
為保證數據的安全性,每個Partition有多個Replica
多Parition的優點
并發讀寫,加快讀寫速度
多Partition分布式存儲,利于集群數據的均衡
加快數據恢復的速率:當某臺機器掛了,每個Topic僅需恢復一部分的數據,多機器并發
缺點
Partition間Msg無序,若想保證Msg寫入與讀取的序不變,只能申請一個Partition
Partition存儲結構
每個Partition分為多個Segment
每個Segment包含兩個文件:log文件和index文件,分別命名為start_offset.log和start_offset.index
log文件包含具體的msg數據,每條msg會有一個遞增的offset
Index文件是對log文件的索引:每隔一定大小的塊,索引msg在該segment中的相對offset和在log文件中的位置偏移量
根據offset查找msg的過程
根據msg的offset和log文件名中的start_offset,找到最后一個不大于msgoffset的segment,即為msg所在的segment;
根據對應segment的index文件,進一步查找msg在log文件中的偏移量
從log文件的偏移量開始讀取解析msg,比較msgoffset,找到所要讀取的msg
Partition recovery過程
每個Partition會在磁盤記錄一個RecoveryPoint, 記錄已經flush到磁盤的最大offset。當broker fail 重啟時,會進行loadLogs。首先會讀取該Partition的RecoveryPoint,找到包含RecoveryPoint的segment及以后的segment, 這些segment就是可能沒有完全flush到磁盤segments。然后調用segment的recover,重新讀取各個segment的msg,并重建索引
優點
以segment為單位管理Partition數據,方便數據生命周期的管理,刪除過期數據簡單
在程序崩潰重啟時,加快recovery速度,只需恢復未完全flush到磁盤的segment
通過命名中offset信息和index文件,大大加快msg查找時間,并且通過分多個Segment,每個index文件很小,查找速度更快
數據流
Partition的多個replica中一個為Leader,其余為follower
Producer只與Leader交互,把數據寫入到Leader中
Followers從Leader中拉取數據進行數據同步
Consumer只從Leader拉取數據
ISR:所有不落后的replica集合, 不落后有兩層含義:距離上次FetchRequest的時間不大于某一個值或落后的消息數不大于某一個值,Leader失敗后會從ISR中選取一個Follower做Leader
數據可靠性保證
當Producer向Leader發送數據時,可以通過acks參數設置數據可靠性的級別
0: 不論寫入是否成功,server不需要給Producer發送Response,如果發生異常,server會終止連接,觸發Producer更新meta數據;
1: Leader寫入成功后即發送Response,此種情況如果Leader fail,會丟失數據
-1: 等待所有ISR接收到消息后再給Producer發送Response,這是最強保證
僅設置acks=-1也不能保證數據不丟失,當Isr列表中只有Leader時,同樣有可能造成數據丟失。要保證數據不丟除了設置acks=-1, 還要保證ISR的大小大于等于2,具體參數設置:
request.required.acks:設置為-1 等待所有ISR列表中的Replica接收到消息后采算寫成功;
min.insync.replicas: 設置為大于等于2,保證ISR中至少有兩個Replica
Producer要在吞吐率和數據可靠性之間做一個權衡
數據一致性保證
一致性定義:若某條消息對client可見,那么即使Leader掛了,在新Leader上數據依然可以被讀到
HW-HighWaterMark: client可以從Leader讀到的最大msg offset,即對外可見的最大offset, HW=max(replica.offset)
對于Leader新收到的msg,client不能立刻消費,Leader會等待該消息被所有ISR中的replica同步后,更新HW,此時該消息才能被client消費,這樣就保證了如果Leader fail,該消息仍然可以從新選舉的Leader中獲取。
對于來自內部Broker的讀取請求,沒有HW的限制。同時,Follower也會維護一份自己的HW,Folloer.HW = min(Leader.HW, Follower.offset)
HDFS數據組織
數據分塊,比如以64M為一個數據塊;
流水線復制:每個數據塊沒有Leader和Follower之分,采用流水線的方式進行數據復制;
就近讀取:為了減少讀取時的網路IO,采用就近讀取,加快讀取速率