成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

消息隊(duì)列二三事

dack / 3232人閱讀

摘要:但是我們明顯能感覺(jué)到這會(huì)降低吞吐量,因?yàn)橄⒉荒懿⑿型哆f了,而且會(huì)阻塞等待,也沒(méi)法發(fā)揮的威力。

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

服務(wù)質(zhì)量 服務(wù)語(yǔ)義

服務(wù)質(zhì)量一般可以分為三個(gè)級(jí)別,下面說(shuō)明它們不同語(yǔ)義。

At most once

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

At least once

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

Exactly once

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

可靠性

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

kafka 中一個(gè)topic有多個(gè)partition,每個(gè)partition又有多個(gè)replica,所有replica中有一個(gè)leader,ISR是一定要同步leader后才能返回提交成功的replica集,OSR內(nèi)的replica盡力的去同步leader,可能數(shù)據(jù)版本會(huì)落后。在kafka工作的過(guò)程中,如果某個(gè)replica同步速度慢于replica.lag.time.max.ms指定的閾值,則被踢出ISR存入OSR,如果后續(xù)速度恢復(fù)可以回到ISR中??梢耘渲?b>min.insync.replicas指定ISR中的replica最小數(shù)量,默認(rèn)該值為1。LEO是分區(qū)的最新數(shù)據(jù)的offset,當(dāng)數(shù)據(jù)寫(xiě)入leader后,LEO就立即執(zhí)行該最新數(shù)據(jù),相當(dāng)于最新數(shù)據(jù)標(biāo)識(shí)位。HW是當(dāng)寫(xiě)入的數(shù)據(jù)被同步到所有的ISR中的副本后,數(shù)據(jù)才認(rèn)為已提交,HW更新到該位置,HW之前的數(shù)據(jù)才可以被消費(fèi)者訪問(wèn),保證沒(méi)有同步完成的數(shù)據(jù)不會(huì)被消費(fèi)者訪問(wèn)到,相當(dāng)于所有副本同步數(shù)據(jù)標(biāo)識(shí)位。

每個(gè)partition的所有replica需要進(jìn)行leader選舉(依賴(lài)ZooKeeper)。在leader宕機(jī)后,只能從ISR列表中選取新的leader,無(wú)論ISR中哪個(gè)副本被選為新的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選擇任何一個(gè)活的replica成為leader然后繼續(xù)工作,此replica可能不在ISR中,就可能導(dǎo)致數(shù)據(jù)丟失。所以實(shí)際使用中需要進(jìn)行可用性可靠性的權(quán)衡。

kafka建議數(shù)據(jù)可靠存儲(chǔ)不依賴(lài)于數(shù)據(jù)強(qiáng)制刷盤(pán)(會(huì)影響整體性能),而是依賴(lài)于replica。

順序消費(fèi)

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

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

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

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

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

性能

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

連接數(shù)

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

kafka的broker采用了類(lèi)似于NettyReactor模型:1(1個(gè)Acceptor線程)+N(N個(gè)Processor線程)+M(M個(gè)Work線程)。
其中Acceptor負(fù)責(zé)監(jiān)聽(tīng)新的連接請(qǐng)求,同時(shí)注冊(cè)OPACCEPT事件,將新的連接按照RoundRobin的方式交給某個(gè)Processor線程處理。
每個(gè)Processor都有一個(gè)NIO selector,向 Acceptor分配的 SocketChannel 注冊(cè) OPREAD、OPWRITE事件,對(duì)socket進(jìn)行讀寫(xiě)。N由num.networker.threads決定。
Worker負(fù)責(zé)具體的業(yè)務(wù)邏輯如:從requestQueue中讀取請(qǐng)求、數(shù)據(jù)存儲(chǔ)到磁盤(pán)、把響應(yīng)放進(jìn)responseQueue中等等。M的大小由num.io.threads決定。

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

QPS

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

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

平均響應(yīng)時(shí)間

平均響應(yīng)時(shí)間是指每個(gè)請(qǐng)求獲得響應(yīng)需要的等待時(shí)間。

kafka中處理請(qǐng)求的瓶頸(也就是最影響響應(yīng)時(shí)間的因素)最有可能出現(xiàn)在哪些地方呢?
網(wǎng)絡(luò)? 有可能,但是這個(gè)因素總體而言不是kafka能控制的,kafka可以對(duì)消息進(jìn)行編碼壓縮并批量提交,減少帶寬占用;
磁盤(pán)? 很有可能,所以kafka從分利用OS的pagecache,并且對(duì)磁盤(pán)采用順序?qū)?/strong>,這樣能大大提升磁盤(pán)的寫(xiě)入速度。同時(shí)kafka還使用了零拷貝技術(shù),把普通的拷貝過(guò)程:disk->read buffer->app buffer->socket buffer->NIC buffer 中,read buffer到app buffer的拷貝過(guò)程省略了(所以上下文切換也減少了),加快了處理速度。這個(gè)功能依賴(lài)于 javatransferTo,底層由 linuxsendfile系統(tǒng)調(diào)用實(shí)現(xiàn)。在 linux2.4及以上 中,數(shù)據(jù)可以直接從 read buffer 拷貝到 NIC buffer ,達(dá)到了最短拷貝路徑。
此外還有文件分段技術(shù),每個(gè)partition都分為多個(gè)segment,避免了大文件操作的同時(shí)提高了并行度。
CPU? 不大可能,因?yàn)橄㈥?duì)列的使用并不涉及大量的計(jì)算,常見(jiàn)消耗有線程切換、編解碼、壓縮解壓、內(nèi)存拷貝等,這些在大數(shù)據(jù)處理中一般不是瓶頸。

并發(fā)數(shù)

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

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

擴(kuò)展性

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

kafka中擴(kuò)展性的基石就是topic采用的partition機(jī)制。第一,Kafka允許Partitioncluster中的Broker之間移動(dòng),以此來(lái)解決數(shù)據(jù)傾斜問(wèn)題。第二,支持自定義的Partition算法,比如你可以將同一個(gè)Key的所有消息都路由到同一個(gè)Partition上去(來(lái)獲得順序)。第三,partition的所有replica通過(guò)ZooKeeper來(lái)進(jìn)行集群管理,可以動(dòng)態(tài)增減副本。第四,partition也支持動(dòng)態(tài)增減。

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

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

參考

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

查看原文,來(lái)自mageekchiu??偨Y(jié)不到位的地方請(qǐng)不吝賜教。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/76905.html

相關(guān)文章

  • RabbitMQ三事

    摘要:路由關(guān)鍵字根據(jù)這個(gè)關(guān)鍵字進(jìn)行消息投遞。則就是根據(jù)不同路由鍵,把消息發(fā)送到某一類(lèi)隊(duì)列中。關(guān)于的一個(gè)重要注意事項(xiàng)是它根據(jù)所謂的節(jié)點(diǎn)名稱(chēng)存儲(chǔ)數(shù)據(jù),默認(rèn)為主機(jī)名。 RabbitMQ概覽 RabbitMQ是一個(gè)高性能的分布式消息中間件。它由Erlang編寫(xiě),這種語(yǔ)言天生支持分布式,而且性能極高(但是比較難上手)。 通信概念 RabbitMQ簡(jiǎn)單理解就是一個(gè)隊(duì)列服務(wù),我們的生產(chǎn)者不斷地往它投遞消息...

    JeOam 評(píng)論0 收藏0
  • PHP多進(jìn)程初探 --- 進(jìn)程間通信三事

    摘要:多進(jìn)程通信之一命名管道。多進(jìn)程通信之三信號(hào)量與共享內(nèi)存。共享內(nèi)存是最快是進(jìn)程間通信方式,因?yàn)閭€(gè)進(jìn)程之間并不需要數(shù)據(jù)復(fù)制,而是直接操控同一份數(shù)據(jù)。的一些書(shū)籍中甚至不建議新手輕易使用這種進(jìn)程間通信的方式,因?yàn)檫@是一種極易產(chǎn)生死鎖的解決方案。 [原文地址:https://blog.ti-node.com/blog...] 往往開(kāi)啟多進(jìn)程的目的是為了一起干活加速效率,前面說(shuō)了不同進(jìn)程之間的內(nèi)存...

    hearaway 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<