国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

消息隊列二三事

dack / 3223人閱讀

摘要:但是我們明顯能感覺到這會降低吞吐量,因為消息不能并行投遞了,而且會阻塞等待,也沒法發揮的威力。

最近在看kafka的代碼,就免不了想看看消息隊列的一些要點:服務質量(QOS)性能擴展性等等,下面一一探索這些概念,并談談在特定的消息隊列如kafka或者mosquito中是如何具體實現這些概念的。

服務質量 服務語義

服務質量一般可以分為三個級別,下面說明它們不同語義。

At most once

至多一次,消息可能丟失,但絕不會重復傳輸。
生產者:完全依賴底層TCP/IP的傳輸可靠性,不做特殊處理,所謂“發送即忘”。kafka中設置acks=0
消費者:先保存消費進度,再處理消息。kafka中設置消費者自動提交偏移量并設置較短的提交時間間隔。

At least once

至少一次,消息絕不會丟,但是可能會重復。
生產者:要做消息防丟失的保證。kafka中設置acks=1 或 all并設置retries>0
消費者:先處理消息,再保存消費進度。kafka中設置消費者自動提交偏移量并設置很長的提交時間間隔,或者直接關閉自動提交偏移量,處理消息后手動調用同步模式的偏移量提交。

Exactly once

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

可靠性

上面的三個語義不僅需要生產者和消費者的配合實現,還要broker本身的可靠性來進行保證。可靠性就是只要broker向producer發出確認,就一定要保證這個消息可以被consumer獲取。

kafka 中一個topic有多個partition,每個partition又有多個replica,所有replica中有一個leaderISR是一定要同步leader后才能返回提交成功的replica集OSR內的replica盡力的去同步leader,可能數據版本會落后。在kafka工作的過程中,如果某個replica同步速度慢于replica.lag.time.max.ms指定的閾值,則被踢出ISR存入OSR,如果后續速度恢復可以回到ISR中。可以配置min.insync.replicas指定ISR中的replica最小數量,默認該值為1。LEO是分區的最新數據的offset,當數據寫入leader后,LEO就立即執行該最新數據,相當于最新數據標識位。HW是當寫入的數據被同步到所有的ISR中的副本后,數據才認為已提交,HW更新到該位置,HW之前的數據才可以被消費者訪問,保證沒有同步完成的數據不會被消費者訪問到,相當于所有副本同步數據標識位。

每個partition的所有replica需要進行leader選舉(依賴ZooKeeper)。在leader宕機后,只能從ISR列表中選取新的leader,無論ISR中哪個副本被選為新的leader,它都知道HW之前的數據,可以保證在切換了leader后,消費者可以繼續看到HW之前已經提交的數據。當ISR中所有replica都宕機該partition就不可用了,可以設置unclean.leader.election.enable=true,該選項使得kafka選擇任何一個活的replica成為leader然后繼續工作,此replica可能不在ISR中,就可能導致數據丟失。所以實際使用中需要進行可用性可靠性的權衡。

kafka建議數據可靠存儲不依賴于數據強制刷盤(會影響整體性能),而是依賴于replica

順序消費

順序消費是指消費者處理消息的順序與生產者投放消息的順序一致。
主要可能破壞順序的場景是生產者投放兩條消息AB,然后A失敗重投遞導致消費者拿到的消息是BA。

kafka中能保證分區內部消息的有序性,其做法是設置max.in.flight.requests.per.connection=1,也就是說生產者在未得到broker對消息A的確認情況下是不會發送消息B的,這樣就能保證broker存儲的消息有序,自然消費者請求到的消息也是有序的。
但是我們明顯能感覺到這會降低吞吐量,因為消息不能并行投遞了,而且會阻塞等待,也沒法發揮 batch 的威力。
如果想要整個topic有序,那就只能一個topic一個partition了,一個consumer group也就只有一個consumer了。這樣就違背了kafka高吞吐的初衷。

重復消費

重復消費是指一個消息被消費者重復消費了。 這個問題也是上面第三個語義需要解決的。

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

性能

衡量一個消息系統的性能有許多方面,最常見的就是下面幾個指標。

連接數

是指系統在同一時刻能支持多少個生產者或者消費者的連接總數。連接數和broker采用的網絡IO模型直接相關,常見模型有:單線程連接每線程ReactorProactor等。
單線程一時刻只能處理一個連接,連接每線程受制于server的線程數量,Reactor是目前主流的高性能網絡IO模型,Proactor由于操作系統對真異步的支持不太行所以尚未流行。

kafka的broker采用了類似于NettyReactor模型:1(1個Acceptor線程)+N(N個Processor線程)+M(M個Work線程)。
其中Acceptor負責監聽新的連接請求,同時注冊OPACCEPT事件,將新的連接按照RoundRobin的方式交給某個Processor線程處理。
每個Processor都有一個NIO selector,向 Acceptor分配的 SocketChannel 注冊 OPREAD、OPWRITE事件,對socket進行讀寫。N由num.networker.threads決定。
Worker負責具體的業務邏輯如:從requestQueue中讀取請求、數據存儲到磁盤、把響應放進responseQueue中等等。M的大小由num.io.threads決定。

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

QPS

是指系統每秒能處理的請求數量。QPS通常可以體現吞吐量(該術語很廣,可以用TPS/QPS、PV、UV、業務數/小時等單位體現)的大小。

kafka中由于可以采用 batch 的方式(還可以壓縮),所以每秒鐘可以處理的請求很多(因為減少了解析量網絡往復次數磁盤IO次數等)。另一方面,kafka每一個topic都有多個partition,所以同一個topic下可以并行(注意不是并發喲)服務多個生產者和消費者,這也提高了吞吐量。

平均響應時間

平均響應時間是指每個請求獲得響應需要的等待時間。

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

并發數

是指系統同時能處理的請求數量數。一般而言,QPS = 并發數/平均響應時間 或者說 并發數 = QPS*平均響應時間

這個參數一般只能估計或者計算,沒法直接測。顧名思義,機器性能越好當然并發數越高咯。此外注意用上多線程技術并且提高代碼的并行度、優化IO模型、減少減少內存分配和釋放等手段都是可以提高并發數的。

擴展性

消息系統的可擴展性是指要為系統組件添加的新的成員的時候比較容易。

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

對于producer,不存在擴展問題,只要broker還夠你連接就行。
對于consumer,一個consumer group中的consumer可以增減,但是最好不要超過一個topicpartition數量,因為多余的consumer并不能提升處理速度,一個partition在同一時刻只能被一個consumer group中的一個consumer消費

代碼上的可擴展性就屬于設計模式的領域了,這里不談。

參考

《kafka技術內幕》
Kafka的存儲機制以及可靠性
Kafka 0.11.0.0 是如何實現 Exactly-once 語義的

查看原文,來自mageekchiu。總結不到位的地方請不吝賜教。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76905.html

相關文章

  • RabbitMQ三事

    摘要:路由關鍵字根據這個關鍵字進行消息投遞。則就是根據不同路由鍵,把消息發送到某一類隊列中。關于的一個重要注意事項是它根據所謂的節點名稱存儲數據,默認為主機名。 RabbitMQ概覽 RabbitMQ是一個高性能的分布式消息中間件。它由Erlang編寫,這種語言天生支持分布式,而且性能極高(但是比較難上手)。 通信概念 RabbitMQ簡單理解就是一個隊列服務,我們的生產者不斷地往它投遞消息...

    JeOam 評論0 收藏0
  • PHP多進程初探 --- 進程間通信三事

    摘要:多進程通信之一命名管道。多進程通信之三信號量與共享內存。共享內存是最快是進程間通信方式,因為個進程之間并不需要數據復制,而是直接操控同一份數據。的一些書籍中甚至不建議新手輕易使用這種進程間通信的方式,因為這是一種極易產生死鎖的解決方案。 [原文地址:https://blog.ti-node.com/blog...] 往往開啟多進程的目的是為了一起干活加速效率,前面說了不同進程之間的內存...

    hearaway 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<