高併發下,如何讓你的數據庫再快一點?

消息隊列(Message Queue)是一種使用高效可靠的數據傳輸機制來進行平臺無關的數據通訊的技術。消息隊列擁有消息傳遞、消息生產、消息消費、優先級消息等功能,爲咱們的分佈式系統提供了數據通訊、功能解耦、彈性伸縮、數據冗餘、限流削峯、異步消息等豐富能力,是分佈式系統的一個重要組件。算法

當前開源的消息隊列的組件種類繁多,在Github上搜索Message Queue,就有4K+的資源。如此衆多的消息隊列的開源項目中,咱們耳熟能詳的有 RabbitMQ、Kafka、RocketMQ、ActiveMQ、Pulsar等等,不少公司也根據業務需求,定製了本身的消息隊列中間件,好比騰訊的CMQ等。這些消息隊列組件各自都有各自的特性與側重點,適合本身的纔是最好的。編程

那麼如何選擇一款最合適的消息隊列組件呢?本文選擇了RabbitMQ以及Kafka這兩款最爲普遍使用的消息中間,來探討一下如何綜合考慮各類因素,好比消費模式、性能、語言支持、社區生態等來選擇一款稱手的消息隊列組件。安全

概述服務器

1、RabbitMQ併發

RabbitMQ是一個歷史比較悠久的消息隊列中間件,最先能夠追溯到2007年,它是使用Erlang語言開發的一個AMQP(Advanced Message Queue Protocol 高級消息隊列協議)實現。AMQP是一個應用層協議的開放標準,爲面向消息的中間件設計,基於此協議的客戶端與消息中間件可傳遞消息,並不受產品、開發語言等條件的限制。RabbitMQ最初起源於金融系統,它在可靠性、可用性、擴展性、消息持久化、高併發等方面的有着卓越的表現。負載均衡

2、Kafka異步

Kafka最先由LinkedIn公司開發,它是一個使用Scala語言開發的支持多分區,多副本而且基於Zookeeper協調的分佈式消息系統。它是一種高吞吐、低延遲、可容錯的分佈式發佈訂閱消息系統,憑藉其可水平擴展的高吞吐率而被普遍使用。在大數據以及流式數據處理方面,Kafka的周邊生態也是其一大優點,愈來愈多的開源分佈式處理系統如 Cloudera、Apache Storm、Spark、Flink等都支持與 Kafka 集成。編程語言

對比分佈式

1、消費模式高併發

消費模式是指消息隊列消費消息是時候的策略,分爲兩種,一種是Push模式,一種是Pull模式。

Push模式是指消息隊列的服務器端收到新的消息時主動將消息推送(Push)到消費端,這種消費模式相好比Pull模式會有更好的實時性,可是當服務器端消息較多時,可能出現消費端來不及消費消息從而壓垮消費端的狀況,須要必定的策略來避免這種狀況的發生。

Pull模式是指消息隊列的服務器不主動將消息推送給消費端,而是有消費端主動地去從服務器拉取(Pull)消息,通常都是定時拉取或者定量拉取的方式。Pull模式相比與Push模式實時性會差一些,其優點在於消費端能夠根據自身消費消息的能力去拉取消息,不會出現消息消費不過來的狀況。

RabbitMQ既支持Push模式同時也支持Pull模式,而Kafka僅支持Pull模式。

2、消息持久化

消息持久化是指將消息隊列中的消息保存至磁盤中,以防止在發生異常或者服務器宕機等突發狀況時發生數據丟失的狀況。消息持久化是保證消息隊列消息可靠性的關鍵技術之一。

RabbitMQ在默認狀況下是不開啓持久化操做,exchange、queue、message等數據都是存儲在內存中的,這意味着若是 RabbitMQ 重啓、關閉、宕機時全部的信息都將丟失。咱們能夠在使用RabbitMQ的時候顯式地將exchange、queue、message 等這些數據對象聲明爲持久化,這樣一來,即使服務器宕機或者故障了,咱們也能夠將這些數據從硬盤中進行恢復。不過須要注意的是,若是RabbitMQ將全部的這些對象都進行持久化操做,會嚴重地影響RabbitMQ的性能,由於同步寫入磁盤的速度會比寫內存慢不少,所以須要在可靠性與性能之間進行權衡。

相比與RabbitMQ須要顯式地指定數據類型的持久化,Kafka在設計之初就是依賴磁盤上的文件系統來進行消息的存儲。從傳統的觀念來說,磁盤的讀寫速度老是比內存慢不少,可是實際上磁盤讀寫速度的快慢取決於咱們的使用方式:

「一塊SATA RAID-5陣列磁盤的線性寫速度能夠達到幾百M_s,而隨機寫的速度只能是100多KB_s,線性寫的速度是隨機寫的上千倍」

Kafka的數據存儲設計是創建在對磁盤文件進行追加寫的基礎上實現的,數據讀取也是順序訪問,這樣的數據存儲設計帶來了很是大的優點:

1. 讀操做不會阻塞寫操做與其餘操做,而且數據大小不會對性能產生影響;

2. 磁盤的容量相比與內存來講會大不少,消息隊列的容量大,而且能夠存儲任意時間,不用擔憂故障致使數據丟失;

綜上所述,RabbitMQ和Kafka均支持消息持久化,可是RabbitMQ須要顯式地開啓持久化,而且開啓持久化可能影響消息隊列性能。而Kafka從設計之初便支持消息持久化,而且經過優秀的設計保證了高效的消息讀寫從而保證了較高的吞吐量。

3、性能

性能是咱們進行技術選型的一個重要的參考維度,對於消息隊列來說,咱們最爲關注的一個性能指標是其吞吐量。在吞吐量這個性能指標上,Kafka基於其優秀的存儲以及讀寫設計,相比於RabbitMQ擁有更高的性能。通常來講RabbitMQ的單機QPS在萬這個級別左右,而Kafka的單機QPS能夠達到十萬級甚至百萬級。

這裏我沒有進行單機的吞吐量性能測試,援引網上的其餘團隊進行的一次消息隊列單機吞吐量性能測試,讓你們感覺一下RabbitMQ與Kafka在吞吐量性能上的差距到底有多少。此次測試對比的是服務端發送小消息(124Byte)的性能,測試的策略是不斷增長髮送端的壓力,直到系統的吞吐量再也不上升,而且系統響應時間增加,這時候服務器端可判斷已出現性能瓶頸,這時候的吞吐量即爲系統的最高吞吐量。

測試的結果以下:

1. Kafka的單機吞吐量爲17.3w/s,達到這個吞吐量時其Broker磁盤IO已經達到了瓶頸,Kafka能達到如此之高的單機吞吐量主要仍是得益於其優秀的設計。

2. RabbitMQ的單機吞吐量爲5.95w/s,而且CPU資源消耗較高,主要緣由是其支持AMQP協議,實現地很是重量級,在消息的可靠性與吞吐量上作了取捨。

因而可知,在吞吐量這個性能指標上,Kafka相比與RabbitMQ是具備明顯的優點的。

說完了吞吐量,讓咱們來討論一下另外一個性能指標:時延。其實在使用消息隊列的場景下討論時延是有些矛盾的,由於使用消息隊列就表明了能夠容許較高的時延,由於使用消息隊列就可能產生消息的堆積,而且消息堆積的越多,從消息生產到消息消費的時延就越高,在對時延要求比較高的場景下使用消息隊列是不合適的,咱們應該使用時延更低的解決方案好比RPC遠程過程調用。

4、可靠性

消息隊列消息的可靠性也是咱們進行技術選型的關鍵考慮因素之一,尤爲涉及到金融、支付、安全等領域,消息的可靠性就顯得尤其重要。保證消息可靠性的關鍵技術之一消息持久化,上文已經討論過,RabbitMQ以及Kafka均支持,咱們這裏不作贅述。這裏咱們來討論一下消息隊列可靠性的另外一個方面,消息投遞(消費)的三種不一樣的保證:

1. 至多一次投遞:消息最多會被投遞一次,可是可能丟失

2. 至少一次投遞:消息至少會被投遞一次,可是可能重複消費

3. 精確一次投遞:保證只會被投遞一次,有且僅有一次

RabbitMQ以及Kafka都支持至多一次投遞以及至少一次投遞的保證,同時Kafka在0.11.0.0版本以後,經過事務機制支持了精確一次投遞的這種保證。

5、可用性

可靠性是保證消息不會丟失或者重複消費,而這裏的可用性則是指系統正常運行時間佔總運行時間的百分比,高可用性也就對應着低故障率,那麼RabbitMQ與Kafka分別有什麼機制來保證系統的高可用呢?

RabbitMQ採用鏡像集羣的策略來保證系統的高可用性,在鏡像集羣模式下,不管是消息隊列仍是消息都會存儲在集羣中的多個實例上。也就是說,對於集羣中的每一個queue來講,集羣中的每一個節點都有這個queue的完整鏡像,這樣一來,即便某個節點宕機了,也不會影響整個集羣的功能。而且即便是某個主節點宕機了,RabbitMQ集羣也能夠經過選主算法選舉新的主節點從而恢復正常服務。

Kafka的高可用性主要源自於其健壯的副本(Replication)策略。其採用的是相似 PacificA 的一致性協議,經過 ISR(In-Sync-Replica)來保證多副本之間的同步,而且支持強一致性語義(經過 acks 實現)。

6、社區生態及語言支持

從長遠的角度來說,社區生態是咱們選擇解決方案考慮的關鍵因素之一,一個開源組件,使用的人越多,社區越活躍,則說明別人踩過的坑也就越多,在咱們開發過程當中遇到問題時就更加容易找到解決方案。同時,若是一個開源組件更新迭代很快,那麼它就能夠迅速修復之前舊版本的問題,同時快速地迭代開發新功能。

在社區生態這方面,整體來講,Kafka的生態以及周邊環境相比於RabbitMQ更加的成熟和豐富,Kafka擁有更多的開源的客戶端、負載均衡組件,同時像Kubernetes、Spark等知名的開源項目也對Kafka有較好的支持。這可能也是得益於在大數據處理方面,Kafka的流式數據的概念和大數據處理更爲的契合。

相比於Kafka,RabbitMQ的社區規模可能會較小一些,可是畢竟也是一個久經考驗的開源消息隊列組件,總的來講咱們在使用過程當中通常也不會遇到社區解決不了的疑難問題。

在語言支持方面,RabbitMQ和Kafka支持的語言都很是的多,Kafka支持大約17種語言,RabbitMQ支持大約22中語言,主流的變成語言如Java、PHP、C++等等二者均支持,相信在使用的編程語言方面不會有太大的問題。

結語

本文就兩種主流的消息隊列組件RabbitMQ和Kafka進行了對比和探討,但願給你們在消息隊列技術選型方面提供必定的思路。你們在選擇的時候要注意結合本身的業務需求,團隊的技術棧體系選擇最爲合適的消息隊列組件!

本文由博客羣發一文多發等運營工具平臺 OpenWrite 發佈

相關文章
相關標籤/搜索