在面試的時候,發現不少面試官特別愛問Kafka相關的問題,這也不難理解,誰讓Kafka是大數據領域中消息隊列的惟一王者,單機十萬級別的吞吐量,毫秒級別的延遲,這種天生的分佈式消息隊列,誰能不愛?
程序員
在最近的一場面試中,有個面試官看到簡歷中的項目上寫Kafka了,就直接開問Kafka,其餘問題基本沒問。下面來看下面試官的Kafka八連問:面試
(如下答案是面試完以後整理而成,實際面試時只回答了大約三分之一)redis
緩衝和削峯:上游數據時有突發流量,下游可能扛不住,或者下游沒有足夠多的機器來保證冗餘,kafka在中間能夠起到一個緩衝的做用,把消息暫存在kafka中,下游服務就能夠按照本身的節奏進行慢慢處理。編程
解耦和擴展性:項目開始的時候,並不能肯定具體需求。消息隊列能夠做爲一個接口層,解耦重要的業務流程。只須要遵照約定,針對數據編程便可獲取擴展能力。安全
冗餘:能夠採用一對多的方式,一個生產者發佈消息,能夠被多個訂閱topic的服務消費到,供多個毫無關聯的業務使用。網絡
健壯性:消息隊列能夠堆積請求,因此消費端業務即便短期死掉,也不會影響主要業務的正常進行。app
異步通訊:不少時候,用戶不想也不須要當即處理消息。消息隊列提供了異步處理機制,容許用戶把一個消息放入隊列,但並不當即處理它。想向隊列中放入多少消息就放多少,而後在須要的時候再去處理它們。異步
kafka消費消息的offset是定義在zookeeper中的, 若是想重複消費kafka的消息,能夠在redis中本身記錄offset的checkpoint點(n個),當想重複消費消息時,經過讀取redis中的checkpoint點進行zookeeper的offset重設,這樣就能夠達到重複消費消息的目的了分佈式
kafka使用的是磁盤存儲。ide
速度快是由於:
注:
- Kafka解決查詢效率的手段之一是將數據文件分段,好比有100條Message,它們的offset是從0到99。假設將數據文件分紅5段,第一段爲0-19,第二段爲20-39,以此類推,每段放在一個單獨的數據文件裏面,數據文件以該段中 小的offset命名。這樣在查找指定offset的
Message的時候,用二分查找就能夠定位到該Message在哪一個段中。- 爲數據文件建 索引數據文件分段 使得能夠在一個較小的數據文件中查找對應offset的Message 了,可是這依然須要順序掃描才能找到對應offset的Message。
爲了進一步提升查找的效率,Kafka爲每一個分段後的數據文件創建了索引文件,文件名與數據文件的名字是同樣的,只是文件擴展名爲.index。
分三個點說,一個是生產者端,一個消費者端,一個broker端。
kafka的ack機制:在kafka發送數據的時候,每次發送消息都會有一個確認反饋機制,確保消息正常的可以被收到,其中狀態有0,1,-1。
若是是同步模式:
ack設置爲0,風險很大,通常不建議設置爲0。即便設置爲1,也會隨着leader宕機丟失數據。因此若是要嚴格保證生產端數據不丟失,可設置爲-1。
若是是異步模式:
也會考慮ack的狀態,除此以外,異步模式下的有個buffer,經過buffer來進行控制數據的發送,有兩個值來進行控制,時間閾值與消息的數量閾值,若是buffer滿了數據尚未發送出去,有個選項是配置是否當即清空buffer。能夠設置爲-1,永久阻塞,也就數據再也不生產。異步模式下,即便設置爲-1。也可能由於程序員的不科學操做,操做數據丟失,好比kill -9,但這是特別的例外狀況。
注:
ack=0:producer不等待broker同步完成的確認,繼續發送下一條(批)信息。
ack=1(默認):producer要等待leader成功收到數據並獲得確認,才發送下一條message。
ack=-1:producer獲得follwer確認,才發送下一條數據。
經過offset commit 來保證數據的不丟失,kafka本身記錄了每次消費的offset數值,下次繼續消費的時候,會接着上次的offset進行消費。
而offset的信息在kafka0.8版本以前保存在zookeeper中,在0.8版本以後保存到topic中,即便消費者在運行過程當中掛掉了,再次啓動的時候會找到offset的值,找到以前消費消息的位置,接着消費,因爲 offset 的信息寫入的時候並非每條消息消費完成後都寫入的,因此這種狀況有可能會形成重複消費,可是不會丟失消息。
惟一例外的狀況是,咱們在程序中給本來作不一樣功能的兩個consumer組設置
KafkaSpoutConfig.bulider.setGroupid的時候設置成了同樣的groupid,這種狀況會致使這兩個組共享同一份數據,就會產生組A消費partition1,partition2中的消息,組B消費partition3的消息,這樣每一個組消費的消息都會丟失,都是不完整的。 爲了保證每一個組都獨享一份消息數據,groupid必定不要重複才行。
每一個broker中的partition咱們通常都會設置有replication(副本)的個數,生產者寫入的時候首先根據分發策略(有partition按partition,有key按key,都沒有輪詢)寫入到leader中,follower(副本)再跟leader同步數據,這樣有了備份,也能夠保證消息數據的不丟失。
採集層 主要可使用Flume, Kafka等技術。
Flume:Flume 是管道流方式,提供了不少的默認實現,讓用戶經過參數部署,及擴展API.
Kafka:Kafka是一個可持久化的分佈式的消息隊列。 Kafka 是一個很是通用的系統。你能夠有許多生產者和不少的消費者共享多個主題Topics。
相比之下,Flume是一個專用工具被設計爲旨在往HDFS,HBase發送數據。它對HDFS有特殊的優化,而且集成了Hadoop的安全特性。
因此,Cloudera 建議若是數據被多個系統消費的話,使用kafka;若是數據被設計給Hadoop使用,使用Flume。
kafka 宕機了,首先咱們考慮的問題應該是所提供的服務是否由於宕機的機器而受到影響,若是服務提供沒問題,若是實現作好了集羣的容災機制,那麼這塊就不用擔憂了。
想要恢復集羣的節點,主要的步驟就是經過日誌分析來查看節點宕機的緣由,從而解決,從新恢復節點。
在 Kafka 中,生產者寫入消息、消費者讀取消息的操做都是與 leader 副本進行交互的,從 而實現的是一種主寫主讀的生產消費模型。
Kafka 並不支持主寫從讀,由於主寫從讀有 2 個很明顯的缺點:
數據一致性問題:數據從主節點轉到從節點必然會有一個延時的時間窗口,這個時間 窗口會致使主從節點之間的數據不一致。某一時刻,在主節點和從節點中 A 數據的值都爲 X, 以後將主節點中 A 的值修改成 Y,那麼在這個變動通知到從節點以前,應用讀取從節點中的 A 數據的值並不爲最新的 Y,由此便產生了數據不一致的問題。
延時問題:相似 Redis 這種組件,數據從寫入主節點到同步至從節點中的過程須要經歷 網絡→主節點內存→網絡→從節點內存 這幾個階段,整個過程會耗費必定的時間。而在 Kafka 中,主從同步會比 Redis 更加耗時,它須要經歷 網絡→主節點內存→主節點磁盤→網絡→從節 點內存→從節點磁盤 這幾個階段。對延時敏感的應用而言,主寫從讀的功能並不太適用。
而kafka的主寫主讀的優勢就不少了: