<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          師兄大廠面試遇到面試官的 Kafka 暴擊三連問,快面哭了!

          共 5591字,需瀏覽 12分鐘

           ·

          2020-09-10 23:22

          一、背景

          前段時間,師兄一直在四處奔波面試中,和我分享了很多面試題和經驗,我都一一拿小本本記下來 ( 超認真 !?。?/p>

          其實在今天的很多面試里,都會要求能夠熟練運用Apache Kafka等至少一種消息隊列,Apache Kafka也是我們 面試里的???。

          但在大多數(shù)人的印象中,寫磁盤都是比較慢的,可是,為什么Apache Kafka在各大MQ性能的評測中,還能夠擊敗眾多對手,取得不錯的成績呢?

          接下來就讓我們通過師兄遇到的關于 Kafka 問題的暴擊三連問 ,走進他受傷的心 ? ....

          二、帶著疑問思考

          1. 「Kafka 為什么快?」
          2. 「Kafka 和其他消息隊列的區(qū)別?」
          3. 「Kafka 這么快,它是如何保證不丟失消息?」

          三、我的回答思路

          其實,在大數(shù)據(jù)開發(fā)崗的面試中,都避免不了 面試官問你 Kafka ,畢竟 Kafka 和 Kafka Streams 耍起來確實很香??!

          那我們就先從 Kafka 的基礎知識了解起吧,還不太了解的小伙伴可以先看看這幾篇博客,先構建一個技術棧的知識框架,這樣在面試時就能做到無懈可擊啦!?

          Kafka
          【Kafka】(一)kafka 簡介與設計、實現(xiàn)分析
          【Kafka】(十)Kafka 如何實現(xiàn)高吞吐量
          【Kafka】(十一)Kafka 的備份機制
          【Kafka】(十四)Kafka 架構深入

          四、關于 Kafka 為什么這么快

          Kafka 的消息是保存或緩存在磁盤上的,一般認為在磁盤上讀寫數(shù)據(jù)是會降低性能的,因為尋址會比較消耗時間,但

          是實際上,Kafka 的特性之一就是高吞吐率。Kafka 之所以能這么快,無非是:「順序寫磁盤、大量使用內存頁 、零拷貝技術的使用」...

          下面我就從數(shù)據(jù)寫入和讀取兩方面分析,為大家分析下為什么 Kafka 速度這么快。

          ?

          數(shù)據(jù)寫入 Kafka 會把收到的消息都寫入到硬盤中,它絕對不會丟失數(shù)據(jù)。為了優(yōu)化寫入速度 Kafka 采用了兩個技術, 順序寫入和 Memory Mapped File 。

          ?

          4.1 順序寫入

          Kafka 會把收到的消息都寫入到硬盤中,它絕對不會丟失數(shù)據(jù)。為了優(yōu)化寫入速度 Kafka 采用了兩個技術, 順序寫入和 MMFile(Memory Mapped File)。

          磁盤讀寫的快慢取決于你怎么使用它,也就是順序讀寫或者隨機讀寫。在順序讀寫的情況下,磁盤的順序讀寫速度和內存持平。因為硬盤是機械結構,每次讀寫都會尋址->寫入,其中尋址是一個“機械動作”,它是最耗時的。「所以硬盤最討厭隨機 I/O,最喜歡順序 I/O」。為了提高讀寫硬盤的速度,Kafka 就是使用順序 I/O。

          而且 Linux 對于磁盤的讀寫優(yōu)化也比較多,包括 read-ahead 和 write-behind,磁盤緩存等。

          如果在內存做這些操作的時候,一個是 Java 對象的內存開銷很大,另一個是隨著堆內存數(shù)據(jù)的增多,Java 的 GC 時間會變得很長。

          使用磁盤操作有以下幾個好處:

          • 磁盤順序讀寫速度超過內存隨機讀寫。

          • JVM 的 GC 效率低,內存占用大。使用磁盤可以避免這一問題。

          • 系統(tǒng)冷啟動后,磁盤緩存依然可用。

          下圖就展示了 Kafka 是如何寫入數(shù)據(jù)的, 每一個 Partition 其實都是一個文件 ,收到消息后 Kafka 會把數(shù)據(jù)插入到文件末尾(虛框部分):這種方法有一個缺陷——沒有辦法刪除數(shù)據(jù) ,所以 Kafka 是不會刪除數(shù)據(jù)的,它會把所有的數(shù)據(jù)都保留下來,每個 消費者(Consumer)對每個 Topic 都有一個 Offset 用來表示讀取到了第幾條數(shù)據(jù) 。一般情況下 Offset 由客戶端 SDK 負責保存 ,會保存到 Zookeeper 里面 。關于存在硬盤中的消息,Kafka 也有它的解決方法,可以基于時間和 Partition 文件的大小,正常 Kafka 是默認七天的保存,也可以通過命令來修改,以 users topic 為例。

          修改kafka 7天 默認保存周期kafka-topics.sh --zookeeper 6 --alter --topic users --config retention.ms=100000

          所以,為了避免磁盤被撐滿的情況,Kakfa 提供了兩種策略來刪除數(shù)據(jù):

          1. 「基于時間」 (默認七天)
          2. 「基于 Partition 文件大小」

          4.2 Memory Mapped Files

          這個和Java NIO中的內存映射基本相同,在大學的計算機原理里我們學過(劃重點),mmf (Memory Mapped Files)直接利用操作系統(tǒng)的Page來實現(xiàn)文件到物理內存的映射,完成之后對物理內存的操作會直接同步到硬盤。mmf 通過內存映射的方式大大提高了IO速率,省去了用戶空間到內核空間的復制。它的缺點顯而易見--不可靠,當發(fā)生宕機而數(shù)據(jù)未同步到硬盤時,數(shù)據(jù)會丟失,Kafka 提供了produce.type參數(shù)來控制是否主動的進行刷新,如果 Kafka 寫入到 mmf 后立即flush再返回給生產者則為同步模式,反之為異步模式。

          Kafka 提供了一個參數(shù) producer.type 來控制是不是主動 Flush:

          • 如果 Kafka 寫入到 mmf 之后就立即 Flush,然后再返回 Producer 叫同步 (Sync)。

          • 如果 Kafka 寫入 mmf 之后立即返回 Producer 不調用 Flush 叫異步 (Async)。

          ?

          數(shù)據(jù)讀取 Kafka 在讀取磁盤時做了哪些優(yōu)化?

          ?

          4.3 基于 Sendfile 實現(xiàn)零拷貝(Zero Copy)

          作為一個消息系統(tǒng),不可避免的便是消息的拷貝,常規(guī)的操作,一條消息,需要從創(chuàng)建者的socket到應用,再到操作系統(tǒng)內核,然后才能落盤。同樣,一條消息發(fā)送給消費者也要從磁盤到內核到應用再到接收者的socket,中間經過了多次不是很有必要的拷貝。

          傳統(tǒng) Read/Write 方式進行網(wǎng)絡文件傳輸,在傳輸過程中,文件數(shù)據(jù)實際上是經過了四次 Copy 操作,其具體流程細節(jié)如下:

          • 調用 Read 函數(shù),文件數(shù)據(jù)被 Copy 到內核緩沖區(qū)。

          • Read 函數(shù)返回,文件數(shù)據(jù)從內核緩沖區(qū) Copy 到用戶緩沖區(qū)

          • Write 函數(shù)調用,將文件數(shù)據(jù)從用戶緩沖區(qū) Copy 到內核與 Socket 相關的緩沖區(qū)。

          • 數(shù)據(jù)從 Socket 緩沖區(qū) Copy 到相關協(xié)議引擎。

          硬盤—>內核 buf—>用戶 buf—>Socket 相關緩沖區(qū)—>協(xié)議引擎

          而 Sendfile 系統(tǒng)調用則提供了一種減少以上多次 Copy,提升文件傳輸性能的方法。在內核版本 2.1 中,引入了 Sendfile 系統(tǒng)調用,以簡化網(wǎng)絡上和兩個本地文件之間的數(shù)據(jù)傳輸。Sendfile 的引入不僅減少了數(shù)據(jù)復制,還減少了上下文切換。相較傳統(tǒng) Read/Write 方式,2.1 版本內核引進的 Sendfile 已經減少了內核緩沖區(qū)到 User 緩沖區(qū),再由 User 緩沖區(qū)到 Socket 相關緩沖區(qū)的文件 Copy。而在內核版本 2.4 之后,文件描述符結果被改變,Sendfile 實現(xiàn)了更簡單的方式,再次減少了一次 Copy 操作。

          Kafka 把所有的消息都存放在一個一個的文件中,當消費者需要數(shù)據(jù)的時候 Kafka 直接把文件發(fā)送給消費者,配合 mmap 作為文件讀寫方式,直接把它傳給 Sendfile。

          4.4 批量發(fā)送

          Kafka允許進行批量發(fā)送消息,producter發(fā)送消息的時候,可以將消息緩存在本地,等到了固定條件發(fā)送到 Kafka 。

          • 等消息條數(shù)到固定條數(shù)。
          • 一段時間發(fā)送一次。

          4.5 數(shù)據(jù)壓縮

          Kafka還支持對消息集合進行壓縮,Producer可以通過GZIP或Snappy格式對消息集合進行壓縮。壓縮的好處就是減少傳輸?shù)臄?shù)據(jù)量,減輕對網(wǎng)絡傳輸?shù)膲毫Α?/p>

          Producer壓縮之后,在Consumer需進行解壓,雖然增加了CPU的工作,但在對大數(shù)據(jù)處理上,瓶頸在網(wǎng)絡上而不是CPU,所以這個成本很值得。

          注意:「批量發(fā)送」「數(shù)據(jù)壓縮」一起使用,單條做數(shù)據(jù)壓縮的話,效果不明顯 ?

          4.6 總結

          以上,便是Apache Kafka雖然使用了硬盤存儲,但是仍然可以速度很快的原因。它把所有的消息都變成一個批量的文件,并且進行合理的批量壓縮,減少網(wǎng)絡 IO 損耗,通過 mmap 提高 I/O 速度。寫入數(shù)據(jù)的時候由于單個 Partion 是末尾添加,所以速度最優(yōu);讀取數(shù)據(jù)的時候配合 Sendfile 直接暴力輸出。

          五、關于 Kafka 和其他消息隊列的區(qū)別

          Kafka的設計目標是高吞吐量,那它與其它消息隊列的區(qū)別就顯而易見了:

          1、Kafka操作的是序列文件I / O(序列文件的特征是按順序寫,按順序讀),為保證順序,Kafka強制點對點的按順序傳遞消息,這意味著,一個consumer在消息流(或分區(qū))中只有一個位置。

          2、Kafka不保存消息的狀態(tài),即消息是否被“消費”。一般的消息系統(tǒng)需要保存消息的狀態(tài),并且還需要以隨機訪問的形式更新消息的狀態(tài)。而Kafka 的做法是保存Consumer在Topic分區(qū)中的位置offset,在offset之前的消息是已被“消費”的,在offset之后則為未“消費”的,并且offset是可以任意移動的,這樣就消除了大部分的隨機IO。

          3、Kafka支持點對點的批量消息傳遞。

          4、Kafka的消息存儲在OS pagecache(頁緩存,page cache的大小為一頁,通常為4K,在Linux讀寫文件時,它用于緩存文件的邏輯內容,從而加快對磁盤上映像和數(shù)據(jù)的訪問)。

          ?

          RabbitMQ:分布式,支持多種MQ協(xié)議,重量級 ActiveMQ:與RabbitMQ類似 ZeroMQ:以庫的形式提供,使用復雜,無持久化 Redis:單機、純內存性好,持久化較差 Kafka:分布式,消息不是使用完就丟失【較長時間持久化】,吞吐量高【高性能】,輕量靈活

          ?

          六、Kafka 如何保證消息隊列不丟失

          我想,如果小伙伴直接遇到面試官問:Kafka 為什么這么快,又能保證不丟失消息?肯定是蒙蔽的,但如果前面回答的僅僅有條,這個時候再回答消息不丟失,就很容易啦 !Σ(っ °Д °;)っ

          6.1 關于 ACK 機制

          關于 ACK 機制 ,不了解的小伙伴,可以看這里:Kafka 架構深入 ,通過 ACK 機制保證消息送達。Kafka 采用的是至少一次(At least once),消息不會丟,但是可能會重復傳輸。

          acks 的默認值即為1,代表我們的消息被leader副本接收之后就算被成功發(fā)送。我們可以配置 acks = all ,代表則所有副本都要接收到該消息之后該消息才算真正成功被發(fā)送。

          6.2 關于設置分區(qū)

          為了保證 leader 副本能有 follower 副本能同步消息,我們一般會為 topic 設置 replication.factor >= 3。這樣就可以保證每個 分區(qū)(partition) 至少有 3 個副本,以確保消息隊列的安全性。

          6.3 關閉 unclean leader 選舉

          我們最開始也說了我們發(fā)送的消息會被發(fā)送到 leader 副本,然后 follower 副本才能從 leader 副本中拉取消息進行同步。多個 follower 副本之間的消息同步情況不一樣,當我們配置了 unclean.leader.election.enable = false 的話,當 leader 副本發(fā)生故障時就不會從 follower 副本中和 leader 同步程度達不到要求的副本中選擇出 leader ,這樣降低了消息丟失的可能性。

          6.4 關于發(fā)送消息

          為了得到更好的性能,Kafka 支持在生產者一側進行本地buffer,也就是累積到一定的條數(shù)才發(fā)送,如果這里設置不當是會丟消息的。

          生產者端設置:producer.type=async, sync,默認是 sync。

          當設置為 async,會大幅提升性能,因為生產者會在本地緩沖消息,并適時批量發(fā)送。

          如果對可靠性要求高,那么這里可以設置為 sync 同步發(fā)送。

          一般時候我們還需要設置:min.insync.replicas> 1 ,消息至少要被寫入到這么多副本才算成功,也是提升數(shù)據(jù)持久性的一個參數(shù),與acks配合使用。

          但如果出現(xiàn)兩者相等,我們還需要設置 replication.factor = min.insync.replicas + 1 ,避免在一個副本掛掉,整個分區(qū)無法工作的情況!

          6.5 Consumer 端丟失消息

          consumer端丟失消息的情形比較簡單:

          如果在消息處理完成前就提交了offset,那么就有可能造成數(shù)據(jù)的丟失。

          由于Kafka consumer默認是自動提交位移的,所以在后臺提交位移前一定要保證消息被正常處理了,因此不建議采用很重的處理邏輯,如果處理耗時很長,則建議把邏輯放到另一個線程中去做。

          為了避免數(shù)據(jù)丟失,現(xiàn)給出幾點建議:設置 enable.auto.commit=false

          關閉自動提交位移,在消息被完整處理之后再手動提交位移。

          以上,便是本篇博客的所有內容,希望師兄大廠面試順利 !

          —?【 THE END 】—
          本公眾號全部博文已整理成一個目錄,請在公眾號里回復「m」獲??!


          3T技術資源大放送!包括但不限于:Java、C/C++,Linux,Python,大數(shù)據(jù),人工智能等等。在公眾號內回復「1024」,即可免費獲?。?!




          瀏覽 44
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  做爱视频无码免费网站 | 臭小子啊轻点灬太粗太长了的视频 | 国产精品三级 | 超碰97人人操 | 一区二区三区四区在线 |