開篇介紹
大家好,近期會整理一些Java高頻面試題分享給小伙伴,也希望看到的小伙伴在找工作過程中能夠用得到!本章節主要針對Java一些消息中間件高頻面試題進行分享。
Q1:
什么是消息和批次?
消息,Kafka里的數據單元,也就是我們一般消息中間件里的消息的概念。消息由字節數組組成。消息還可以包含鍵,用以對消息選取分區。
為了提高效率,消息被分批寫入Kafka。
批次,就是一組消息,這些消息屬於同一個主題和分區。如果只傳遞單個消息,會導致大量的網絡開銷,把消息分成批次傳輸可以減少這開銷。但是,這個需要權衡,批次里包含的消息越多,單位時間內處理的消息就越多,單個消息的傳輸時間就越長。如果進行壓縮,可以提升數據的傳輸和存儲能力,但需要更多的計算處理。
Q2:
什么是主題和分區?
Kafka的消息用主題進行分類,主題下可以被分為若干個分區。分區本質上是個提交日志,有新消息,這個消息就會以追加的方式寫入分區,然后用先入先出的順序讀取。
但是因為主題會有多個分區,所以在整個主題的范圍內,是無法保證消息的順序的,單個分區則可以保證。
Kafka通過分區來實現數據冗余和伸縮性,因為分區可以分布在不同的服務器上,那就是說一個主題可以跨越多個服務器。
前面我們說Kafka可以看成一個流平台,很多時候,我們會把一個主題的數據看成一個流,不管有多少個分區。
Q3:
Kafka中的ISR、AR代表什么?ISR的伸縮指的什么?
-
ISR :In-Sync Replicas 副本同步隊列
-
AR :Assigned Replicas 所有副本
ISR是由leader維護,follower從leader同步數據有一些延遲(包括 延遲時間replica.lag.time.max.ms 和 延遲條數replica.lag.max.message 兩個維度,當前最新的版本0.10.x中只支持 replica.lag.time.max.ms 這個維度),任意一個超過閾值都會把follower剔除出ISR,存入OSR(Outof-Sync Replicas)列表,新加入的follower也會先存放在OSR中。
注:AR = ISR + OSR
Q4:
Broker 和 集群
一個獨立的Kafka服務器叫Broker。broker的主要工作是,接收生產者的消息,設置偏移量,提交消息到磁盤保存;為消費者提供服務,響應請求,返回消息。在合適的硬件上,單個broker可以處理上千個分區和每秒百萬級的消息量。
多個broker可以組成一個集群。每個集群中broker會選舉出一個集群控制器。控制器會進行管理,包括將分區分配給broker和監控broker。
集群里,一個分區從屬於一個broker,這個broker被稱為首領。但是分區可以被分配給多個broker,這個時候會發生分區復制。
分區復制帶來的好處是,提供了消息冗余。一旦首領broker失效,其他broker可以接管領導權。當然相關的消費者和生產者都要重新連接到新的首領上。
Q5:
kafka中的zookeeper起到什么作用?
zookeeper是一個分布式的協調組件,早期版本的kafaka用zk做 meta信息存儲 , consumer的消費狀態 , group的管理 以及 offset 的值。
考慮到zk本身的一些因素以及整個架構較大概率存在單點問題,新版本中逐漸弱化了zookeeper的作用。新的consumer使用了kafka內部的 group coordination 協議,也減少了對zookeeper的依賴。
Q6:
kafka follower如何與leader數據同步?
kafka的復制機制既不是完全的同步復制,也不是單純的異步復制。
完全同步復制要求 All Alive Follower 都復制完,這條消息才會被認為commit,這種復制方式極大的影響了吞吐率。
一步復制方式下,Follower異步的從Leader復制數據,數據只要被Leader寫入log就被認為已經commit,這種情況下,如果leader掛掉,會丟失數據;
kafka使用 ISR 的方式很好的均衡了確保數據不丟失以及吞吐率。Follower可以批量的從Leader復制數據,而且Leader充分利用磁盤順序讀以及 send file(zero copy) 機制,這樣極大的提高復制性能,內部批量寫磁盤,大幅減少了Follower與Leader的消息量差。
Q7:
kafka中的消息是否會丟失和重復消費?
消息發送:
kafka消息發送有兩種方式:同步(sync)和異步(async);
默認是同步方式,可通過 producer.type 屬性進行配置;
kafka通過配置 request.required.acks 屬性來確認消息的生產。
-
0:表示不進行消息接收是否成功的確認;
-
1:表示當Leader接收成功時確認;
-
-1:表示Leader和Follower都接收成功時確認;
綜上所述,有6種消息產生的情況,消息丟失的場景有:
-
acks=0,不和kafka集群進行消息接收確認,則當網絡異常、緩沖區滿了等情況時,消息可能丟失;
-
acks=1、同步模式下,只有Leader確認接收成功后但掛掉了,副本沒有同步,數據可能丟失;
消息消費:
kafka消息消費有兩個consumer接口, Low-level API 和 High-level API :
-
Low-level API:消費者自己維護offset等值,可以實現對kafka的完全控制;
-
High-level API:封裝了對parition 和 offset 的管理,使用簡單;
如果使用高級接口High-level API,可能存在一個問題就是當消息消費者從集群中把消息取出來,並提交了新的消息offset值后,還沒來得及消費就掛掉了,那么下次再消費時之前沒消費成功的消息就"詭異"的消失了;
解決方案:
1 針對消息丟失:同步模式下,確認機制設置為-1,即讓消息寫入Leader 和 Follower之后再確認消息發送成功;異步模式下,為防止緩沖區滿,可以在配置文件設置不限制阻塞超時時間,當緩沖區滿時讓生產者一直處於阻塞狀態。
2 針對消息重復:將消息的唯一標識保存到外部介質中,每次消費時判斷是否處理過即可。
Q8:
kafka為什么不支持讀寫分離?
在kafka中,生產者寫入消息、消費者讀取消息的操作都是與Leader副本進行交互的,從而實現的是一種主寫主讀的生產消費模型。
kafka並不支持主寫從讀,因為主寫從讀有2個很明顯的缺點:
-
數據一致性問題:數據從主節點轉到從節點必然會有一個延時的時間窗口,這個時間窗口會導致主從節點之間的數據不一致。某一時刻,在主節點和從節點中A數據的值都為X,之后將主節點中A的值修改為Y,那么在這個變更通知到從節點之前,應用讀取從節點中的A數據的值並不為最新的Y值,由此便產生了數據不一致的問題。
-
延時問題:類似Redis這種組件,數據從寫入主節點到同步至從節點的過程中需要經歷 網絡→主節點內存→網絡→從節點內存 這幾個階段,整個過程會耗費一定的時間。而在kafka中,主從同步會比Redis更加耗時,它需要經歷 網絡→主節點內存→主節點磁盤→網絡→從節點內存→從節點磁盤 這幾個階段。對延時敏感的應用而言,主寫從讀的功能場景並不太適用。
點關注、不迷路
如果覺得文章不錯,歡迎關注、點贊、收藏,你們的支持是我創作的動力,感謝大家。
如果文章寫的有問題,請不要吝嗇,歡迎留言指出,我會及時核查修改。
如果你還想更加深入的了解我,可以私信我。每天8:00准時推送技術文章,讓你的上班路不在孤獨,而且每月還有送書活動,助你提升硬實力!



