最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

消息隊列之 MetaQ 和 Kafka 哪個更香!

2023-07-26 17:36 作者:阿里云  | 我要投稿

消息隊列

消息隊列是一個用于接收消息、存儲消息并且轉(zhuǎn)發(fā)消息的中間件,主要是用于解決如下的場景:

  • 異步:A服務做了一些事情,異步發(fā)送消息給服務B;

  • 削峰/限流:類似一個蓄水池,比如說有些服務(例如電商服務的秒殺),請求量很高,服務端處理不過來,那么請求先放到消息隊列里面,然后服務端按照自己的能力來消費處理;

  • 解耦:應用之間減少代碼的耦合,使得應用的部署更加靈活;

消息隊列有幾個重要的概念模型:消息、隊列、生產(chǎn)者、消費者,下面將介紹這幾個基本概念:

  • 消息:消息是消息隊列中的最基本概念,其本質(zhì)上是一段數(shù)據(jù),能夠被多個應用程序所理解,是應用程序之間傳遞信息的載體,消息一般是由消息描述符和消息體組成;

  • 隊列:隊列是一種先進先出的數(shù)據(jù)結構,隊列是由隊列頭部和隊列尾部組成,一般需要在隊列尾部進行插入,在隊列頭部進行刪除;

  • 生產(chǎn)者:生產(chǎn)者主要是用來產(chǎn)生消息,并將消息放入隊列的尾部;

  • 消費者:消費者主要是用來消費隊列頭部的消息;

MetaQ介紹

目前常用的消息中間件有kafka、RocketMQ和ActiveMQ等;今天我們將介紹MetaQ,MetaQ也是消息隊列中間件,屬于阿里內(nèi)部的RocketMQ,下面將介紹MetaQ的相關概念:

? ? ? ??

圖片

NameServer

命名服務,內(nèi)部維護了topic和broker之間的對應關系,并且和所有broker保持心跳連接,在producer和consumer需要發(fā)布或者消費消息的時候,向nameserver發(fā)出請求來獲取連接的broker的信息;

NameServer可以部署多個,每個之間互相獨立,其他角色同時向多個NameServer機器上報狀態(tài)信息,從而達到熱備份的目的;

NameServer類似kafka中zookeeper的角色,那為什么不直接采用ZooKeeper角色呢,那是因為ZooKeeper有自動選舉Master的功能,MetaQ的架構設計上決定了它不需要進行Master選舉,而只需要使用一個輕量級的元數(shù)據(jù)服務器就可以了。

Broker

MetaQ的服務器,負責消息的中轉(zhuǎn)、存儲和轉(zhuǎn)發(fā),Broker可以分為Master和Slave,一個Master可以對接多個Slave,但是一個Slave只能對接一個Master,Master與Slave之間可以通過指定相同的BrokerName,不同的BrokerId來定義,BrokerId為0表示Master,不為0的表示Slave。

Master可以部署多個,每個Broker和NameServer集群中的所有節(jié)點建立長連接,定期的注冊Topic信息到所有的NameServer上。

消息會發(fā)送到Master上,一旦Master上面記錄成功,就直接返回成功,不用等待slave上面是否記錄成功,slave會定時的去獲取消息記錄,所以slave和master上面會有一些時間差異;slave可以作為consumer的服務提供者,意思就是如果寫入必須通過master,消費的時候則可以直接從slave上面獲取。Master和slave都需要注冊到nameserver上面,一旦master無法使用,客戶端可以使用與之對應的slave。

每個Broker與Name Server集群中的所有節(jié)點建立長連接,定時(每隔30s)注冊Topic信息到所有Name Server。Name Server定時(每隔10s)掃描所有存活broker的連接,如果Name Server超過2分鐘沒有收到心跳,則Name Server斷開與Broker的連接。

Topic

Topic,即為發(fā)布或者訂閱的主題,topic一般由多個隊列組成,隊列會平均的散列到多個Broker上面。Producer的發(fā)送機制會保證消息盡量平均的散列到所有隊列上面去,最終的效果是所有的消息會平均的落在每個Broker上面。

Tag屬于子Topic,主要的作用是給業(yè)務提供更大的靈活性,用以分流信息。

Producer

Producer,即消息的生產(chǎn)者,負責生產(chǎn)消息,producer的和Name server集群中隨機的一個節(jié)點建立長連接,定期從nameServer中獲取Topic路由信息,并向提供topic服務的master broker建立長連接,并定時向master發(fā)送心跳。producer會發(fā)布消息到master上面,然后由master同步給所有的slave。

Producer每隔30s從Name server獲取所有topic隊列的最新情況,這意味著如果Broker不可用,Producer最多30s能夠感知,在此期間內(nèi)發(fā)往Broker的所有消息都會失敗。

Producer每隔30s向所有關聯(lián)的broker發(fā)送心跳,Broker每隔10s中掃描所有存活的連接,如果Broker在2分鐘內(nèi)沒有收到心跳數(shù)據(jù),則關閉與Producer的連接。

Consumer

Consumer,即消息的消費者,負責消費消息,consumer與nameserver集群中的隨機一個節(jié)點建立長連接,定期的從nameServer中獲取topic路由信息,并向提供Topic服務的Master、Slave建立長連接,并且定時向Master、Slave發(fā)送心跳。Consumer既可以從Master上面訂閱消息,也可以從Slave上面訂閱消息,訂閱規(guī)則由Broker配置決定。

Consumer每隔30s從Name server獲取topic的最新隊列情況,這意味著Broker不可用時,Consumer最多最需要30s才能感知。

Consumer每隔30s(由ClientConfig中heartbeatBrokerInterval決定)向所有關聯(lián)的broker發(fā)送心跳,Broker每隔10s掃描所有存活的連接,若某個連接2分鐘內(nèi)沒有發(fā)送心跳數(shù)據(jù),則關閉連接;并向該Consumer Group的所有Consumer發(fā)出通知,Group內(nèi)的Consumer重新分配隊列,然后繼續(xù)消費。

ConsumerGroup

ConsumerGroup,即消費者集群,多個消費者可以組成一個分組,擁有一個共同的分組名稱,來共同消費一個topic下的消息,每個消費者消費部分消息。

Message

Message,即生產(chǎn)或者消費的消息,負載用戶的數(shù)據(jù)并且在producer、broker和consumer之間傳輸。

Offset

消息在Broker上的每個分區(qū)都是組織成一個文件列表,消費者拉取數(shù)據(jù)的時候需要知道數(shù)據(jù)在文件中的偏移量,這個偏移量就是offset。Offset是一個絕對的偏移量,服務器會將offset轉(zhuǎn)化為具體文件的相對偏移量。

Kafka和MetaQ之對比

Kafka和MetaQ存儲機制

Kafka存儲機制

Kafka和MetaQ一樣,都是采用topic作為發(fā)布和訂閱的主題,topic是個邏輯概念,而partition是物理上面的概念,每個partition對應一個log文件,該log文件中存儲的就是producer生產(chǎn)的數(shù)據(jù)。producer生產(chǎn)的數(shù)據(jù)會被不斷追加到log文件的末端,且每條數(shù)據(jù)都有自己的offset。

每個Partition都會有自己的副本,Kafka會盡量的使所有的分區(qū)均勻的分布到集群中的所有節(jié)點而不是集中在某些節(jié)點上,另外主從關系也盡量均衡這樣每個幾點都會擔任一定比例的分區(qū)的leader。

? ? ? ??

圖片

每個partition以目錄的形式存儲在broker上,該目錄底下存儲著的是該partition內(nèi)容被平均分配成的多個大小相等的數(shù)據(jù)文件,我們稱之為segment(段)。每個segment文件分為兩個部分,index file和data file,此兩個文件一一對應,后綴".index"和".log"分別表示segment的索引文件和數(shù)據(jù)文件。文件的命名規(guī)則為partition全局的第一個segment為0開始,后續(xù)每個segment文件名為上一個全局partion的最大offset(偏移message數(shù))。每個segment中存儲很多條消息,消息id由其邏輯位置決定,即從消息id可直接定位到消息的存儲位置,避免id到位置的額外映射。

segment index file采取稀疏索引存儲方式,它減少索引文件大小,通過mmap可以直接內(nèi)存操作,稀疏索引為數(shù)據(jù)文件的每個對應message設置一個元數(shù)據(jù)指針,先通過index文件中獲取該message的一個位置范圍,然后根據(jù)這個位置范圍在log文件中找到該message的信息。

? ? ? ??

圖片

MetaQ存儲機制

MetaQ的消息存儲方式和kafka的partition存放方式類似,在MetaQ中消息的存放分為物理隊列和邏輯隊列。

物理隊列:物理隊列我們一般用commitlog來表示,在一個broker上面,所有發(fā)到broker上的信息都會按順序?qū)懭胛锢黻犃兄校锢黻犃杏钟稍S多文件組成,當一個文件被寫滿(默認大小為1G)時,則創(chuàng)建一個新的文件繼續(xù)寫入,文件以offset的方式來命名,與kafka中的partition命名類似。

邏輯隊列:邏輯隊列我們一般用consumequeue來表示,在消息被寫入物理隊列之后,如果消費端想從broker拉取消息,就需要一個索引文件,MetaQ中將每個Topic分為了幾個區(qū),每個區(qū)對應了一個消費隊列,不過這些消費隊列只是由一個個索引文件組成。消費端在拉取消息的時候,只要知道自己訂閱的Topic從nameserver獲取broker地址建立連接之后,就能根據(jù)消費隊列中的索引文件,去物理隊列中獲取訂閱的消息。

CommitLog以物理文件的方式存放,每臺Broker上的CommitLog被本機器上所有的ConsumeQueue共享。在CommitLog中,一個消息的存儲長度是不固定的,MetaQ中采取了一些機制,盡量往CommitLog中順序?qū)懀强梢灾С蛛S機讀。ConsumeQueue的內(nèi)容也會被寫到磁盤里進行持久存儲,但是ConsumeQueue的內(nèi)容是通過異步刷盤的方式進行。

? ??? ??? ??

圖片

為什么MetaQ需要采用這種存儲架構呢?

我們知道,磁盤的順序?qū)懕入S機寫的速度快的很多,目前的高性能磁盤,順序?qū)懙乃俣瓤梢赃_到600MB/s,超過了一般的網(wǎng)卡的傳輸速度,但是磁盤的隨機寫的速度只有大概100KB/s,和順序?qū)懙男阅芟嗖盍?000倍,而MetaQ正是利用磁盤順序?qū)懙膬?yōu)勢來設計的。

上文說到,MetaQ的主要存儲文件包括CommitLog、ConsumeQueue文件,在一個Broker節(jié)點上,MetaQ會將所有Topic的消息存儲在同一個文件commitlog中,這樣能確保producer發(fā)送的消息順序?qū)懭隿ommitlog中,能夠盡最大的能力確保消息發(fā)送的高性能和高吞吐量,接收消息的時候,只有CommitLog是需要同步落盤的。同時使用ConsumeQueue消息隊列文件來作為索引文件,每個Topic包含有多個消息消費隊列,每一個消息隊列就有一個ConsumeQueue消息文件,ConsumeQueue是異步保存的,不需要同步落盤,如果在沒有落盤的時候,broker發(fā)生宕機,MetaQ可以根據(jù)CommitLog來恢復ConsumeQueue。

雖然說在同一個broker上面由于不同的ConsumeQueue訪問同一個CommitLog,CommitLog是進行隨機讀的,但是根據(jù)操作系統(tǒng)的局部性原理,也利用操作系統(tǒng)的分頁機制,可以批量的從磁盤中獲取CommitLog的信息,然后緩存到內(nèi)存中,更快的進行讀取。而對于ConsumeQueue,由于其內(nèi)部只保存數(shù)據(jù)的索引信息,所以一般其數(shù)據(jù)量不大,可以全部讀入內(nèi)存,所以我們可以認為從ConsumeQueue這個中間結構獲取數(shù)據(jù)很快,可以當成從內(nèi)存讀取數(shù)據(jù)的速度。

在kafka中,當如果一個broker上面有多個partition,如果多個partition并發(fā)寫入數(shù)據(jù),磁盤的訪問會有很大的瓶頸,多個文件之間必然會有磁盤的尋道。而MetaQ對于數(shù)據(jù)來說就只有單文件寫入,性能上將優(yōu)于kafka。

MetaQ為什么不像Kafka使用zk作為元數(shù)據(jù)節(jié)點,而要使用自己實現(xiàn)的NameServer?

我們知道,kafka使用zk作為元數(shù)據(jù)節(jié)點,起到了Broker注冊、Topic注冊、生產(chǎn)者和消費者負載均衡以及使用zk進行l(wèi)eader角色的選舉,當leader所在的broker掛了,將會經(jīng)過以下兩步操作重新選舉leader:第1步,先通過Zookeeper在所有機器中,選舉出一個KafkaController;第2步,再由這個Controller,決定每個partition的Master是誰,Slave是誰。因為有了選舉功能,所以kafka某個partition的master掛了,該partition對應的某個slave會升級為主對外提供服務。? ??? ??

MetaQ不具備選舉,Master/Slave的角色也是固定的。當一個Master掛了之后,你可以寫到其他Master上,但不能讓一個Slave切換成Master。那么MetaQ是如何實現(xiàn)高可用的呢,其實很簡單,MetaQ的所有broker節(jié)點的角色都是一樣,上面分配的topic和對應的queue的數(shù)量也是一樣的,MetaQ只能保證當一個broker掛了,把原本寫到這個broker的請求遷移到其他broker上面,而并不是這個broker對應的slave升級為主。? ??? ??

圖片

引入zk的主要目的是為了選主,kafka中如果一個broker掛了,這個broker上面的主partition可以通過zk的選舉機制在其他broker上面選舉主partition,而對于MateQ而言,在部署的時候已經(jīng)決定了這個Broker是主或者是備了(一個Master可以對接多個Slave,但是一個Slave只能對接一個Master,Master與Slave之間可以通過指定相同的BrokerName,不同的BrokerId來定義,BrokerId為0表示Master,不為0的表示Slave),不能再通過選舉變成主(認命吧,無法上位的),所以對于MetaQ,是不需要進行選舉的,為了方便集群維護,直接使用NameServer這一個輕量級工具來存儲元數(shù)據(jù)信息即可。

MetaQ和kafka的部署方式

由上文可知,MetaQ和kafka的元數(shù)據(jù)節(jié)點采用的方式不一樣,MetaQ的master和slave都是物理上隔離的,所以對于MetaQ的Broker來說,是支持以下四種方式的部署:

  • 單Master:單機模式, 即只有一個Broker, 如果Broker宕機了, 會導致MetaQ服務不可用, 不推薦使用;

  • 多Master模式:?組成一個集群, 集群每個節(jié)點都是Master節(jié)點, 配置簡單, 性能也是最高, 某節(jié)點宕機重啟不會影響MetaQ服務;

缺點是如果某個節(jié)點宕機了, 會導致該節(jié)點存在未被消費的消息在節(jié)點恢復之前不能被消費;

  • 多Master多Slave模式,異步復制:每個Master配置一個Slave, 多對Master-Slave, Master與Slave消息采用異步復制方式, 主從消息一致只會有毫秒級的延遲;

優(yōu)點是彌補了多Master模式(無slave)下節(jié)點宕機后在恢復前不可訂閱的問題。在Master宕機后, 消費者還可以從Slave節(jié)點進行消費。采用異步模式復制,提升了一定的吞吐量??偨Y一句就是,采用多Master多Slave模式,異步復制模式進行部署,系統(tǒng)將會有較低的延遲和較高的吞吐量;

缺點就是如果Master宕機, 磁盤損壞的情況下, 如果沒有及時將消息復制到Slave, 會導致有少量消息丟失;

  • 多Master多Slave模式,同步雙寫:與多Master多Slave模式,異步復制方式基本一致,唯一不同的是消息復制采用同步方式,只有master和slave都寫成功以后,才會向客戶端返回成功。

優(yōu)點:數(shù)據(jù)與服務都無單點,Master宕機情況下,消息無延遲,服務可用性與數(shù)據(jù)可用性都非常高

缺點就是會降低消息寫入的效率,并影響系統(tǒng)的吞吐量;

對于Kafka來說,Broker之間不存在master和slave的區(qū)別,每一個Broker之間都是平等的,kafka的partition是有master和slave的區(qū)別的,kafka將每個partition數(shù)據(jù)復制到多個server上,任何一個partition有一個leader和多個follower(可以沒有);備份的個數(shù)可以通過broker配置文件來設定。leader處理所有的read-write請求,follower需要和leader保持同步。Kafka盡量的使所有分區(qū)均勻的分布到集群所有的節(jié)點上而不是集中在某些節(jié)點上,另外主從關系也盡量均衡這樣每個幾點都會擔任一定比例的分區(qū)的leader。

MetaQ和kafka的消息可靠性

在介紹MetaQ和kafka的消息可靠性之前,我們先來介紹一下幾個概念:同步異步復制、同步異步刷盤。

1)同步異步復制

同步復制和異步復制的區(qū)別在于producer發(fā)送消息到master節(jié)點之后,是否會等待slave節(jié)點復制結束之后再進行返回。

a.同步復制

當生產(chǎn)者將消息發(fā)送到broker的master節(jié)點時,master會首先將消息復制到所有的slave節(jié)點,等待復制動作完成之后,才會給客戶端返回“發(fā)送成功”的響應,消息可靠性得到保證。

? ??? ??

圖片

b.異步復制

當生產(chǎn)者將消息發(fā)送到broker的master節(jié)點時,并不會等待復制動作的結束,會直接返回一個發(fā)送成功的狀態(tài)響應。當出現(xiàn)網(wǎng)絡抖動,會導致消息復制不成功,這個時候消息可靠性不夠高,消費者消費消息不及時的情況。? ??? ??

圖片

2)同步異步刷盤

同步異步刷盤的區(qū)別在于,消息存儲在內(nèi)存(memory)中以后,是否會等待執(zhí)行完刷盤動作再返回,即是否會等待將消息中的消息寫入磁盤中。

a. 異步刷盤

當消息寫入到broker的內(nèi)存中之后即返回寫成功狀態(tài),并不會等待消息從內(nèi)存中寫入磁盤就返回。所以寫操作的返回快,吞吐量大;當內(nèi)存里的消息量積累到一定程度時,統(tǒng)一觸發(fā)寫磁盤操作,快速寫入。? ??? ??

圖片

b. 同步刷盤

當消息被寫入到內(nèi)存之后,會立刻會立刻通知刷盤線程刷盤,然后等待刷盤完成,刷盤線程執(zhí)行完成后喚醒等待的線程,返回消息寫成功的狀態(tài)。所以當返回寫成功狀態(tài)的時候,消息已經(jīng)被寫入磁盤了。? ??? ??? ??

圖片

MetaQ和kafka都支持同步異步復制以及同步異步刷盤。

MetaQ的同步異步復制是通過Broker的配置文件中的brokerRole參數(shù)進行設置的,這個參數(shù)可以被設置成ASYNC_MASTER、SYNC_MASTER、SLAVE三個值中的一個。其中ASYNC_MASTER表示的是當前broker的角色是一個異步復制的master,生產(chǎn)者寫入消息到Master后無需等待消息復制到slave即可返回;SYNC_MASTER表示當前的broker的角色是一個同步復制的master,Master寫入完消息之后,需要等待Slave的復制成功,但是這邊注意這里只需要有一個Slave復制成功并成功應答即算成功;SLAVE表示的是當前broker是一個slave。

MetaQ的同步異步刷盤是通過Broker配置文件里的flushDiskType參數(shù)設置的,這個參數(shù)被設置成SYNC_FLUSH, ASYNC_FLUSH中的一個,其中SYNC_FLUSH表示同步刷盤,ASYNC_FLUSH表示異步刷盤。

Kafka的同步異步復制可以通過acks配置來實現(xiàn),當acks的參數(shù)設置為0,表示生產(chǎn)者把消息發(fā)送出去之后,不管消息有沒有被接收,直接就認為消息發(fā)送成功;當acks的參數(shù)設置為1,表示生產(chǎn)者把消息發(fā)送出去之后,就認為消息發(fā)送成功,而不管其他的slave是否同步這個消息,相當于異步復制,該配置為kafka的默認配置;當acks的參數(shù)設置為all,表示生產(chǎn)者把消息發(fā)送出去之后,master收到消息之后,還必須等待ISR列表中跟master保持同步的那些slave都進行消息同步之后,才認為消息寫入成功,相當于同步復制。

kafka可以通過配置flush.message和flush.ms來設置刷盤策略,如果flush.message設置為5,表示每5條消息進行一次刷盤,如果flush.message設置為1,表示每一條消息都進行一次刷盤。如果flush.ms設置為1000,表示每過1000ms進行一次刷盤,如果flush.ms設置為5000,表示每過5000ms進行一次刷盤。

MetaQ和kafka的消息讀寫方式

零拷貝

我們知道,我們在寫數(shù)據(jù)的時候并不是直接寫入到磁盤中去的,而是寫入到pageCache中去的,pageCache的主要作用是減少磁盤的I/O操作。

在磁盤寫入的時候會寫入到pageCache中去的,然后pageCache中可以將一些小的寫入合并成一個大的寫入,再進行異步刷盤。當然我們也可以使用fsync進行強制刷盤,強制刷盤會影響寫入性能。一般為了保證消息的可靠性,我們是會采用多副本來存儲消息,而不是采用同步刷盤。

讀取消息的時候如果在pageCache中有命中則直接返回,如果在pageCache中無法命中則會產(chǎn)生缺頁中斷,需要從磁盤中加載數(shù)據(jù)到緩存中,然后返回數(shù)據(jù)。并且根據(jù)局部性原理,在讀數(shù)據(jù)的時候也會進行預讀,把該也相鄰的磁盤快讀入到頁緩存中去。

mmap

由于我們讀取數(shù)據(jù)的時候,需要將數(shù)據(jù)從磁盤拷貝到pageCache中,但是由于pageCache屬于內(nèi)核空間,用戶空間無法訪問,所以還需要將數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間。? ??? ??? ??? ??

圖片

所以數(shù)據(jù)需要兩次拷貝應用程序才能夠訪問的到,我們可以通過mmap來減少數(shù)據(jù)從內(nèi)核態(tài)到用戶態(tài)的拷貝。通過將程序虛擬頁面映射到頁緩存中,這樣就不需要將數(shù)據(jù)從內(nèi)核態(tài)拷貝到用戶態(tài),也可以避免產(chǎn)生重復數(shù)據(jù)。也不必要再通過調(diào)用read和write方法對文件進行讀寫,而是通過映射地址和偏移量來直接操作pageCache。? ??? ??? ??? ??

圖片

sendfile

下面我們來看下常規(guī)的發(fā)送文件的過程中,從磁盤讀取消息到發(fā)送文件的過程是怎么樣的。

? ? ? ? ? ? ? ??

圖片

DMA Copy是指不需要CPU接入,可以直接讀寫系統(tǒng)內(nèi)存,類似顯卡、網(wǎng)卡和磁盤都是用到DMA,然而像上下文切換的話就需要有CPU接入。

下面我們看看如果采用mmap發(fā)送文件之后的流程是怎么樣的。

? ??? ??? ??? ??

圖片

可以看到上下文切換的次數(shù)沒有變化,但是數(shù)據(jù)少拷貝了一份,這個和我們上面說到的mmap所能夠達到的效果是一樣的。

? ??? ??? ??? ??

圖片

上圖中,sendfile采用一次系統(tǒng)調(diào)用就完成了發(fā)送數(shù)據(jù)的需求,相比于read+write或者說mmap+write來說上下文切換次數(shù)變少了,但是數(shù)據(jù)還是有冗余的。在linux2.4中采用 sendfile+帶[分散-收集]的DMA。真正實現(xiàn)了無冗余的功能。

? ??? ??? ??? ??

圖片

上面就是我們說的零拷貝,在Java中是通過FileChannal.transferTo()調(diào)用的,底層是通過sendfile實現(xiàn)。

MetaQ和kafka的讀寫對比

目前kafka支持sendfile的消息讀寫方式,MetaQ支持mmap的消息讀寫方式,另外MetaQ還支持sendfile的消息寫方式。

默認情況下,MetaQ不論是在CommitLog或者ComsumerQueue中都是采用mmap來實現(xiàn)消息讀寫的。在發(fā)送消息的時候,通常情況下會將數(shù)據(jù)拷貝到堆內(nèi)存中去,然后再塞到響應體中進行發(fā)送。當然我們也可以通過參數(shù)配置不經(jīng)過堆,通過mapedBuffer直接發(fā)送到SocketBuffer。

當消費消息的時候,嚴格來說對于CommitLog的讀取是隨機的,因為CommitLog的消息是混合進行存儲的,但是從整體上面來看,消息還是會從CommitLog上順序讀取的,先讀取舊數(shù)據(jù),然后再讀取新數(shù)據(jù)。消息存進去之后很快就會被消費,這個時候消息還是存放在pageCache中的,所以我們是不需要讀取磁盤的。

? ??? ??? ??? ??? ??

圖片

同時pageCache會定時刷盤,但是刷盤的時機是不可控制的,所以會出現(xiàn)swap等現(xiàn)象。mmap也只是做了映射,如果真正去取數(shù)據(jù)的時候不在內(nèi)存中,也會產(chǎn)生缺頁中斷,需要加載數(shù)據(jù)到內(nèi)存中,這個時候也會有一些延時。MetaQ采用文件預分配和文件預熱來解決pageCache的不確定性。

kafka的消息寫入對于單分區(qū)來說是順序?qū)懭氲?,由上文可知,kafka是有.index索引文件和.log數(shù)據(jù)文件構成的。其中.index索引文件是采用mmap進行讀寫的,這對于本地讀寫索引文件則可以提高讀取效率,而.log數(shù)據(jù)文件則采用sendfile的零拷貝進行實現(xiàn)的。對于消息的寫入來說,采用mmap其實并沒有什么用,因為消息都是從網(wǎng)絡中獲取的,采用sendfile來發(fā)送消息比mmap+write更能提高效率,因為在內(nèi)存中少了一個SocketBuffer的拷貝。

另外通過網(wǎng)上研究測試表明,如果讀取的數(shù)據(jù)小于4kb的時候,使用mmap的性能效率比sendfile高,當讀取數(shù)據(jù)大于4kb的時候,sendfile的效率比mmap高;對于寫數(shù)據(jù),如果寫入的數(shù)據(jù)包小于64kb的時候,mmap的性能效率比sendfile高,當寫入數(shù)據(jù)包大于64kb的時候sendfile的效率比mmap高。

由于kafka主要是用于日志傳輸,處理海量數(shù)據(jù),對于數(shù)據(jù)的正確度要求不是很高,并且在發(fā)送消息的時候一般會進行消息的匯聚,然后批量發(fā)送消息,所以整體上來說kafka的讀寫數(shù)據(jù)量會比較大,這個時候使用sendfile能夠獲取更高的性能,而MetaQ主要是用來針對阿里的復雜應用場景,對于數(shù)據(jù)的可靠性、數(shù)據(jù)的實時性要求會比較高,由于對數(shù)據(jù)的實時性要求較高,一般不會進行匯聚批量發(fā)送消息,所以讀寫數(shù)據(jù)量不會很大,這個時候使用mmap可以獲得更好的性能,當如果發(fā)現(xiàn)寫入的數(shù)據(jù)量比較大時,也可以切換為sendfile進行寫入。


消息隊列之 MetaQ 和 Kafka 哪個更香!的評論 (共 條)

分享到微博請遵守國家法律
陈巴尔虎旗| 新泰市| 蒙山县| 海口市| 泸西县| 开封市| 手机| 广东省| 荣成市| 康马县| 定南县| 文化| 醴陵市| 张家口市| 太康县| 定陶县| 文成县| 林甸县| 琼海市| 云安县| 北票市| 南陵县| 黑龙江省| 嘉禾县| 汝城县| 金塔县| 东海县| 柳河县| 宜阳县| 大连市| 新蔡县| 图们市| 五台县| 福安市| 大名县| 峨眉山市| 海淀区| 湖北省| 呼和浩特市| 绩溪县| 乐陵市|