消息隊(duì)列二三事

最近在看kafka的代碼夏跷,就免不了想看看消息隊(duì)列的一些要點(diǎn):服務(wù)質(zhì)量(QOS)蒸苇、性能擴(kuò)展性等等算撮,下面一一探索這些概念,并談?wù)勗谔囟ǖ南㈥?duì)列如kafka或者mosquito中是如何具體實(shí)現(xiàn)這些概念的县昂。

服務(wù)質(zhì)量

服務(wù)語義

服務(wù)質(zhì)量一般可以分為三個級別肮柜,下面說明它們不同語義。

At most once

至多一次倒彰,消息可能丟失审洞,但絕不會重復(fù)傳輸。
生產(chǎn)者:完全依賴底層TCP/IP的傳輸可靠性待讳,不做特殊處理芒澜,所謂“發(fā)送即忘”。kafka中設(shè)置acks=0创淡。
消費(fèi)者:先保存消費(fèi)進(jìn)度痴晦,再處理消息。kafka中設(shè)置消費(fèi)者自動提交偏移量并設(shè)置較短的提交時間間隔琳彩。

At least once

至少一次誊酌,消息絕不會丟部凑,但是可能會重復(fù)。
生產(chǎn)者:要做消息防丟失的保證碧浊。kafka中設(shè)置acks=1 或 all并設(shè)置retries>0涂邀。
消費(fèi)者:先處理消息,再保存消費(fèi)進(jìn)度箱锐。kafka中設(shè)置消費(fèi)者自動提交偏移量并設(shè)置很長的提交時間間隔比勉,或者直接關(guān)閉自動提交偏移量,處理消息后手動調(diào)用同步模式的偏移量提交瑞躺。

Exactly once

精確一次,每條消息肯定會被傳輸一次且僅一次兴想。
這個級別光靠消息隊(duì)列本身并不好保證幢哨,有可能要依賴外部組件。
生產(chǎn)者:要做消息防丟失的保證嫂便。kafka中設(shè)置acks=1 或 all并設(shè)置retries>0捞镰。mosquito中通過四步握手與DUP、MessageID等標(biāo)識來實(shí)現(xiàn)單次語義毙替。
消費(fèi)者:要做消息防重復(fù)的保證岸售,有多種方案,如:在保存消費(fèi)進(jìn)度和處理消息這兩個操作中引入兩階段提交協(xié)議厂画;讓消息冪等凸丸;讓消費(fèi)處理與進(jìn)度保存處于一個事務(wù)中來保證原子性。kafka中關(guān)閉自動提交偏移量袱院,并設(shè)置自定義的再平衡監(jiān)聽器屎慢,監(jiān)聽到分區(qū)發(fā)生變化時從外部組件讀取或者存儲偏移量,保證自己或者其他消費(fèi)者在更換分區(qū)時能讀到最新的偏移量從而避免重復(fù)忽洛∧寤荩總之就是結(jié)合ConsumerRebalanceListenerseek和一個外部系統(tǒng)(如支持事務(wù)的數(shù)據(jù)庫)共同來實(shí)現(xiàn)單次語義欲虚。此外集灌,kafka還提供了GUID以便用戶自行實(shí)現(xiàn)去重。kafka 0.11版本通過3個大的改動支持EOS:1.冪等的producer复哆;2. 支持事務(wù)欣喧;3. 支持EOS的流式處理(保證讀-處理-寫全鏈路的EOS)。
這三個級別可靠性依次增加梯找,但是延遲帶寬占用也會增加续誉,所以實(shí)際情況中,要依據(jù)業(yè)務(wù)類型做出權(quán)衡初肉。

可靠性

上面的三個語義不僅需要生產(chǎn)者和消費(fèi)者的配合實(shí)現(xiàn)酷鸦,還要broker本身的可靠性來進(jìn)行保證。可靠性就是只要broker向producer發(fā)出確認(rèn),就一定要保證這個消息可以被consumer獲取臼隔。

kafka 中一個topic有多個partition嘹裂,每個partition又有多個replica,所有replica中有一個leader摔握,ISR是一定要同步leader后才能返回提交成功的replica集寄狼,OSR內(nèi)的replica盡力的去同步leader,可能數(shù)據(jù)版本會落后氨淌。在kafka工作的過程中泊愧,如果某個replica同步速度慢于replica.lag.time.max.ms指定的閾值,則被踢出ISR存入OSR盛正,如果后續(xù)速度恢復(fù)可以回到ISR中删咱。可以配置min.insync.replicas指定ISR中的replica最小數(shù)量豪筝,默認(rèn)該值為1痰滋。LEO是分區(qū)的最新數(shù)據(jù)的offset,當(dāng)數(shù)據(jù)寫入leader后续崖,LEO就立即執(zhí)行該最新數(shù)據(jù)敲街,相當(dāng)于最新數(shù)據(jù)標(biāo)識位。HW是當(dāng)寫入的數(shù)據(jù)被同步到所有的ISR中的副本后严望,數(shù)據(jù)才認(rèn)為已提交多艇,HW更新到該位置,HW之前的數(shù)據(jù)才可以被消費(fèi)者訪問像吻,保證沒有同步完成的數(shù)據(jù)不會被消費(fèi)者訪問到墩蔓,相當(dāng)于所有副本同步數(shù)據(jù)標(biāo)識位。

每個partition的所有replica需要進(jìn)行leader選舉(依賴ZooKeeper)萧豆。在leader宕機(jī)后奸披,只能從ISR列表中選取新的leader,無論ISR中哪個副本被選為新的leader涮雷,它都知道HW之前的數(shù)據(jù)阵面,可以保證在切換了leader后,消費(fèi)者可以繼續(xù)看到HW之前已經(jīng)提交的數(shù)據(jù)洪鸭。當(dāng)ISR中所有replica都宕機(jī)該partition就不可用了样刷,可以設(shè)置unclean.leader.election.enable=true,該選項(xiàng)使得kafka選擇任何一個活的replica成為leader然后繼續(xù)工作览爵,此replica可能不在ISR中置鼻,就可能導(dǎo)致數(shù)據(jù)丟失。所以實(shí)際使用中需要進(jìn)行可用性可靠性的權(quán)衡蜓竹。

kafka建議數(shù)據(jù)可靠存儲不依賴于數(shù)據(jù)強(qiáng)制刷盤(會影響整體性能)箕母,而是依賴于replica储藐。

順序消費(fèi)

順序消費(fèi)是指消費(fèi)者處理消息的順序與生產(chǎn)者投放消息的順序一致。
主要可能破壞順序的場景是生產(chǎn)者投放兩條消息AB嘶是,然后A失敗重投遞導(dǎo)致消費(fèi)者拿到的消息是BA钙勃。

kafka中能保證分區(qū)內(nèi)部消息的有序性,其做法是設(shè)置max.in.flight.requests.per.connection=1聂喇,也就是說生產(chǎn)者在未得到broker對消息A的確認(rèn)情況下是不會發(fā)送消息B的辖源,這樣就能保證broker存儲的消息有序,自然消費(fèi)者請求到的消息也是有序的希太。
但是我們明顯能感覺到這會降低吞吐量克饶,因?yàn)橄⒉荒懿⑿型哆f了,而且會阻塞等待誊辉,也沒法發(fā)揮 batch 的威力矾湃。
如果想要整個topic有序,那就只能一個topic一個partition了芥映,一個consumer group也就只有一個consumer了洲尊。這樣就違背了kafka高吞吐的初衷远豺。

重復(fù)消費(fèi)

重復(fù)消費(fèi)是指一個消息被消費(fèi)者重復(fù)消費(fèi)了奈偏。 這個問題也是上面第三個語義需要解決的。

一般的消息系統(tǒng)如kafka或者類似的rocketmq都不能也不提倡在系統(tǒng)內(nèi)部解決躯护,而是配合第三方組件惊来,讓用戶自己去解決。究其原因還是解決問題的成本解決問題后獲得的價值不匹配棺滞,所以干脆不解決裁蚁,就像操作系統(tǒng)對待死鎖一樣,采取“鴕鳥政策”继准。
但是kafka 0.11還是處理了這個問題枉证,見發(fā)行說明,維護(hù)者是想讓用戶無可挑剔嘛 [笑cry]移必。

性能

衡量一個消息系統(tǒng)的性能有許多方面室谚,最常見的就是下面幾個指標(biāo)。

連接數(shù)

是指系統(tǒng)在同一時刻能支持多少個生產(chǎn)者或者消費(fèi)者的連接總數(shù)崔泵。連接數(shù)和broker采用的網(wǎng)絡(luò)IO模型直接相關(guān)秒赤,常見模型有:單線程連接每線程憎瘸、Reactor入篮、Proactor等。
單線程一時刻只能處理一個連接幌甘,連接每線程受制于server的線程數(shù)量潮售,Reactor是目前主流的高性能網(wǎng)絡(luò)IO模型痊项,Proactor由于操作系統(tǒng)對真異步的支持不太行所以尚未流行。

kafka的broker采用了類似于NettyReactor模型:1(1個Acceptor線程)+N(N個Processor線程)+M(M個Work線程)饲做。
其中Acceptor負(fù)責(zé)監(jiān)聽新的連接請求线婚,同時注冊OPACCEPT事件,將新的連接按照RoundRobin的方式交給某個Processor線程處理盆均。
每個Processor都有一個NIO selector塞弊,向 Acceptor分配的 SocketChannel 注冊 OPREAD、OPWRITE事件泪姨,對socket進(jìn)行讀寫游沿。N由num.networker.threads決定。
Worker負(fù)責(zé)具體的業(yè)務(wù)邏輯如:從requestQueue中讀取請求肮砾、數(shù)據(jù)存儲到磁盤诀黍、把響應(yīng)放進(jìn)responseQueue中等等。M的大小由num.io.threads決定仗处。

Reactor模型一般基于IO多路復(fù)用(如select眯勾,epoll),是非阻塞的婆誓,所以少量的線程能處理大量的連接吃环。
如果大量的連接都是idle的,那么Reactor使用epoll的效率是杠杠的洋幻,如果大量的連接都是活躍的郁轻,此時如果沒有Proactor的支持就最好把epoll換成select或者poll
具體做法是-Djava.nio.channels.spi.SelectorProvidersun.nio.ch包下面的EPollSelectorProvider換成PollSelectorProvider文留。

QPS

是指系統(tǒng)每秒能處理的請求數(shù)量好唯。QPS通常可以體現(xiàn)吞吐量(該術(shù)語很廣燥翅,可以用TPS/QPS骑篙、PV、UV森书、業(yè)務(wù)數(shù)/小時等單位體現(xiàn))的大小靶端。

kafka中由于可以采用 batch 的方式(還可以壓縮),所以每秒鐘可以處理的請求很多(因?yàn)闇p少了解析量拄氯、網(wǎng)絡(luò)往復(fù)次數(shù)躲查、磁盤IO次數(shù)等)。另一方面译柏,kafka每一個topic都有多個partition镣煮,所以同一個topic下可以并行(注意不是并發(fā)喲)服務(wù)多個生產(chǎn)者和消費(fèi)者,這也提高了吞吐量鄙麦。

平均響應(yīng)時間

平均響應(yīng)時間是指每個請求獲得響應(yīng)需要的等待時間典唇。

kafka中處理請求的瓶頸(也就是最影響響應(yīng)時間的因素)最有可能出現(xiàn)在哪些地方呢镊折?
網(wǎng)絡(luò)? 有可能介衔,但是這個因素總體而言不是kafka能控制的恨胚,kafka可以對消息進(jìn)行編碼壓縮并批量提交,減少帶寬占用炎咖;
磁盤赃泡? 很有可能,所以kafka從分利用OS的pagecache乘盼,并且對磁盤采用順序?qū)?/strong>升熊,這樣能大大提升磁盤的寫入速度。同時kafka還使用了零拷貝技術(shù)绸栅,把普通的拷貝過程:disk->read buffer->app buffer->socket buffer->NIC buffer 中级野,內(nèi)核buffer到用戶buffer的拷貝過程省略了,加快了處理速度粹胯。此外還有文件分段技術(shù)蓖柔,每個partition都分為多個segment,避免了大文件操作的同時提高了并行度风纠。
CPU况鸣? 不大可能,因?yàn)橄㈥?duì)列的使用并不涉及大量的計(jì)算议忽,常見消耗有線程切換懒闷、編解碼十减、壓縮解壓栈幸、內(nèi)存拷貝等,這些在大數(shù)據(jù)處理中一般不是瓶頸帮辟。

并發(fā)數(shù)

是指系統(tǒng)同時能處理的請求數(shù)量數(shù)速址。一般而言,QPS = 并發(fā)數(shù)/平均響應(yīng)時間 或者說 并發(fā)數(shù) = QPS*平均響應(yīng)時間由驹。

這個參數(shù)一般只能估計(jì)或者計(jì)算芍锚,沒法直接測。顧名思義蔓榄,機(jī)器性能越好當(dāng)然并發(fā)數(shù)越高咯并炮。此外注意用上多線程技術(shù)并且提高代碼的并行度、優(yōu)化IO模型甥郑、減少減少內(nèi)存分配和釋放等手段都是可以提高并發(fā)數(shù)的逃魄。

擴(kuò)展性

消息系統(tǒng)的可擴(kuò)展性是指要為系統(tǒng)組件添加的新的成員的時候比較容易。

kafka中擴(kuò)展性的基石就是topic采用的partition機(jī)制澜搅。第一伍俘,Kafka允許Partitioncluster中的Broker之間移動邪锌,以此來解決數(shù)據(jù)傾斜問題。第二癌瘾,支持自定義的Partition算法觅丰,比如你可以將同一個Key的所有消息都路由到同一個Partition上去(來獲得順序)。第三妨退,partition的所有replica通過ZooKeeper來進(jìn)行集群管理妇萄,可以動態(tài)增減副本。第四咬荷,partition也支持動態(tài)增減嚣伐。

對于producer,不存在擴(kuò)展問題萍丐,只要broker還夠你連接就行轩端。
對于consumer,一個consumer group中的consumer可以增減逝变,但是最好不要超過一個topicpartition數(shù)量基茵,因?yàn)槎嘤嗟?code>consumer并不能提升處理速度,一個partition在同一時刻只能被一個consumer group中的一個consumer消費(fèi)

代碼上的可擴(kuò)展性就屬于設(shè)計(jì)模式的領(lǐng)域了壳影,這里不談拱层。

參考

《kafka技術(shù)內(nèi)幕》
Kafka的存儲機(jī)制以及可靠性
Kafka 0.11.0.0 是如何實(shí)現(xiàn) Exactly-once 語義的

查看原文,來自mageekchiu宴咧「疲總結(jié)不到位的地方請不吝賜教。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末掺栅,一起剝皮案震驚了整個濱河市烙肺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌氧卧,老刑警劉巖桃笙,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異沙绝,居然都是意外死亡搏明,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門闪檬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來星著,“玉大人,你說我怎么就攤上這事粗悯⌒檠” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長邮丰。 經(jīng)常有香客問我行您,道長,這世上最難降的妖魔是什么剪廉? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任娃循,我火速辦了婚禮,結(jié)果婚禮上斗蒋,老公的妹妹穿的比我還像新娘捌斧。我一直安慰自己,他們只是感情好泉沾,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布捞蚂。 她就那樣靜靜地躺著,像睡著了一般跷究。 火紅的嫁衣襯著肌膚如雪姓迅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天俊马,我揣著相機(jī)與錄音丁存,去河邊找鬼。 笑死柴我,一個胖子當(dāng)著我的面吹牛解寝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播艘儒,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼聋伦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了界睁?” 一聲冷哼從身側(cè)響起觉增,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎晕窑,沒想到半個月后抑片,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卵佛,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡杨赤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了截汪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疾牲。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖衙解,靈堂內(nèi)的尸體忽然破棺而出阳柔,到底是詐尸還是另有隱情,我是刑警寧澤蚓峦,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布舌剂,位于F島的核電站济锄,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏霍转。R本人自食惡果不足惜荐绝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望避消。 院中可真熱鬧低滩,春花似錦、人聲如沸岩喷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纱意。三九已至婶溯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間偷霉,已是汗流浹背爬虱。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留腾它,地道東北人跑筝。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像瞒滴,于是被迫代替她去往敵國和親曲梗。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 姓名:周小蓬 16019110037 轉(zhuǎn)載自:http://blog.csdn.net/YChenFeng/art...
    aeytifiw閱讀 34,708評論 13 425
  • 背景介紹 Kafka簡介 Kafka是一種分布式的妓忍,基于發(fā)布/訂閱的消息系統(tǒng)虏两。主要設(shè)計(jì)目標(biāo)如下: 以時間復(fù)雜度為O...
    高廣超閱讀 12,820評論 8 167
  • Kafka簡介 Kafka是一種分布式的,基于發(fā)布/訂閱的消息系統(tǒng)世剖。主要設(shè)計(jì)目標(biāo)如下: 以時間復(fù)雜度為O(1)的方...
    Alukar閱讀 3,074評論 0 43
  • “認(rèn)識完了定罢,現(xiàn)在可以說明你的來意了吧,杰西卡小姐旁瘫?或者我還是該稱呼您‘神誡’法師團(tuán)團(tuán)長好些祖凫!” “哦,你知道‘神誡...
    考拉兇猛閱讀 205評論 0 0
  • 很長時間里酬凳,我的文字里很少觸碰“人物”惠况,更不曾寫過“女人”。只因人物通靈宁仔,而女人更是難以道盡的物種稠屠。 小時...
    Mrs十月閱讀 880評論 2 0