Kafak是基於發佈訂閱的消息系統。是一個分佈式,可分區,冗餘備份的持久化的消息系統。主要用戶處理活躍的流式數據。算法
幾個重要基本的概念:緩存
1.Topic :主題,特指Kafak處理的消息源的不一樣分類。app
2.Partition: Topic物理上的分組,一個Topic能夠分爲多個partition.每一個Partition都有一個有序的隊列。Partition中的每一個消息都會分配一個有序的id(offset).dom
replicas:Partition的副本集,保證partition的高可用。異步
leader:repliocas中的一個角色,producer和consumer只和Leader交互。async
followers:replicas中的一個角色,從leader中的複製數據,做爲副本,一旦leader掛掉,從他的followers中選出一個新的leader繼續提供服務。分佈式
3.Message:消息,通訊的基本單位,每一個Producer能夠向一個Topic發送消息 性能
4.Producer:消息和數據的生產者操作系統
5.Consumer:消息和數據的消費者線程
6.Broker :緩存代理,kafak集羣中一臺或者多臺機器統稱broker。
7.zookeeper:經過Zookeeperl來存儲進羣的topic,partition等信息。
Kafak爲何要將topic進行分區:
1.topic是邏輯概念,面向的是producer和consumer,而partition是物理概念。若是Topic不進行分區,而將Topic內全部的消息都存儲在一個broker,那麼關於該Topic的全部讀寫都將由一個borker處理,吞吐量很容易有瓶頸。
2.有了Partition概念之後,假設一個topic被分爲10個partition,kafak會根據必定算法將10個Partition儘量分配到不一樣的broker.
3.當partition發佈消息時,producer客戶端能夠採用random,key-hash輪詢等算法選定partition
4.當consumer消費消息時候,Consumer客戶端能夠採用range,輪詢等算法分配partition,從而在不一樣的broker拉取對應的Partition的leader分區。
因此,在partition機制能夠極大的提升系統的吞吐量,而且使得系統具備良好的水平擴展能力。
Kafak的消息發送和消費的基本流程:
1.Producer:根據指定的partition方法(random,hash等),將消息發送給指定topic的partition.
producer採用push進行模式將消息發佈到Broker,每條消息將append到partition中,屬於順序寫磁盤。Producer會將消息發送到到broker時候,會根據分區算法將其存儲到哪個partition。
寫入流程:
1.Producer先從zk中找到partition的leader。
2.producer將數據發送給leader。
3.leader將消息寫入本地log。
4.followers從leaderpull消息,寫入本地log向leader發送ack。
5.leader收到全部的ISR中的replicas的cas後,增長HW,並像producer發送ack。
Producer的消費發送模式:經過 producer.type進行配置
1.默認同步sync。 能夠保證消息的可靠性
2.能夠設置成爲異步async。能夠是producer以batch的形似push數據。這樣極大提升了Brokder性能。
2.Kafak集羣:接收到producer發送過來的消息,將其持久化到硬盤,並保留消息指定時長。
物理上將Topic分爲多個partition,每一個partition物理上對應一個文件夾(文件夾存儲改partition的全部消息和索引文件)
3.Consumer:從kafak集羣pull數據,並控制獲取消息的offset.至於消費的進度,可手動或者自動提交給kafak集羣。pull模式能夠自主控制消費的速率,同時Consumer能夠控制消費方式,可批量消費也能夠逐條消費。同時還能選擇不一樣的提交方式。
一個消息只能被group內的一個comsumer所消費,且consumer消費消息時不關注offset,最後一個offset有zk保存。下次消費時,該group中的Consumer將從offset記錄的位置開始消費。
注意:1.若是消費線程大於Partition數量,有些線程將收不到消息。
2.若是partition數量大於消費線程數,那麼一個線程將會接收多個partition的消息。
3.若是一個消費線程消費多個partition,則沒法保證你接受到消息的順序,而一個partition內的消息是有序的。
Kafak的數據存儲模型:
Kafak的每一個topic下面的全部消息都是以Partition的方式存儲在多個節點上。同時在kafak的機器上,每一個partition其實會對應一個日誌目錄,在目錄下面上會對應多個日誌分段(LogSegment)。
LogSegment文件由兩部分組成,分別爲.index文件和.log文件,分別用來存儲索引和數據。這兩個文件的命名規則爲:Partition全局的第一個segment從0開始,後續每一個segment文件爲上一個segment文件最後最後一條消息的offset值。
Kafak如何讀取offset數據:
若是咱們要讀取911條數據
首先:第一步,找到他屬於哪一段,根據二分查找找到屬於他的文件,找到0000900.index和0000900.log以後。
而後,去.index中查找(911-900)=11這個索引或者小於11最近的索引,在這裏 經過二分查找咱們找到的索引是[10,1367]
10表示,第10條消息開始。1367表示,在.log的第1367字節開始。
而後,咱們經過這條索引的物理位置1367,開始日後查找,直到找到911條數據。
大多數狀況下,只需按照順序讀便可。而在順序讀中,操做系統會對內存和磁盤之間添加page cahe,也就是咱們日常見的預讀操做,因此咱們順序讀時候速度很快。可是Kafak有個問題,就是分區過多,那麼日誌分段也會不少,寫的時候因爲是批量寫,其實就是會變成隨機寫了。
爲什麼不以partition爲最小存儲單位,能夠想象當producer不停的發送消息,必然會引發partition文件的不一樣擴張,將對消息文件的維護以及已經消費的消息的清理帶來嚴重的影響。