目前市面上比較常用的 MQ(Message Queue,消息隊列)中間件有 RabbitMQ、Kafka、RocketMQ,如果是輕量級的消息隊列可以使用 Redis 提供的消息隊列,其中 Redis 屬於輕量級的消息隊列,而 RabbitMQ、Kafka 屬於比較成熟且比較穩定和高效的 MQ 中間件。
RabbitMQ
RabbitMQ 是一個老牌開源的消息中間件,它實現了標准的 AMQP(Advanced Message Queuing Protocol,高級消息隊列協議)消息中間件,使用 Erlang 語言開發,支持集群部署,和多種客戶端語言混合調用,它支持的主流開發語言有以下這些:
Java and Spring、.NET、Ruby、Python、PHP、JavaScript and Node、Objective-C and Swift、Rust、Scala、Go......更多支持語言,請點擊這里訪問官網查看。
重要的概念
RabbitMQ 中有 3 個重要的概念:生產者、消費者和代理。
生產者:消息的創建者,負責創建和推送數據到消息服務器。
消費者:消息的接收方,用於處理數據和確認消息。
代理:也就是 RabbitMQ 服務本身,它用於扮演“快遞”的角色,因為它本身並不生產消息,只是扮演了“快遞”的角色,把消息進行暫存和傳遞。
運行流程
RabbitMQ 優點
• 支持持久化,RabbitMQ 支持磁盤持久化功能,保證了消息不會丟失;
• 高並發,RabbitMQ 使用了 Erlang 開發語言,Erlang 是為電話交換機開發的語言,天生自帶高並發光環和高可用特性;
• 支持分布式集群,正是因為 Erlang 語言實現的,因此 RabbitMQ 集群部署也非常簡單,只需要啟動每個節點並使用 --link 把節點加入到集群中即可,並且 RabbitMQ 支持自動選主和自動容災;
• 支持多種語言,比如 Java、.NET、PHP、Python、JavaScript、Ruby、Go 等;
• 支持消息確認,支持消息消費確認(ack)保證了每條消息可以被正常消費;
• 它支持很多插件,比如網頁控制台消息管理插件、消息延遲插件等,RabbitMQ 的插件很多並且使用都很方便。
RabbitMQ 的消息類型
(1)direct(默認類型)模式,此模式為一對一的發送方式,也就是一條消息只會發送給一個消費者;
(2)headers 模式,允許你匹配消息的 header 而非路由鍵(RoutingKey),除此之外 headers 和 direct 的使用完全一致,但因為 headers 匹配的性能很差,幾乎不會被用到;
(3)fanout 模式,為多播的方式,會把一個消息分發給所有的訂閱者;
(4)topic 模式,為主題訂閱模式,允許使用通配符(#、*)匹配一個或者多個消息,我可以使用“cn.mq.#”匹配到多個前綴是“cn.mq.xxx”的消息,比如可以匹配到“cn.mq.rabbit”、“cn.mq.kafka”等消息。
RabbitMQ 集群
RabbitMQ 集群是由多個節點組成,但默認情況下每個節點並不是存儲所有隊列的完整拷貝,這是出於存儲空間和性能的考慮,因為如果存儲了隊列的完整拷貝,那么就會有很多冗余的重復數據,並且在新增節點的情況下,不但沒有新增存儲空間,反而需要更大的空間來存儲舊的數據;同樣的道理,如果每個節點都保存了所有隊列的完整信息,那么非查詢操作的性能就會很慢,就會需要更多的網絡帶寬和磁盤負載來存儲這些數據。
為了能兼顧性能和穩定性,RabbitMQ 集群的節點分為兩種類型,即磁盤節點和內存節點,對於磁盤節點來說顯然它的優勢就是穩定,可以把相關數據保存下來,若 RabbitMQ 因為意外情況宕機,重啟之后保證了數據不丟失;而內存節點的優勢是快,因為是在內存中進行數據交換和操作,因此性能比磁盤節點要高出很多倍。
如果是單個 RabbitMQ 那么就必須要求是磁盤節點,否則當 RabbitMQ 服務器重啟之后所有的數據都會丟失,這樣顯然是不能接受的。在 RabbitMQ 的集群中,至少需要一個磁盤節點,這樣至少能保證集群數據的相對可靠性。如果集群中的某一個磁盤節點崩潰了,此時整個 RabbitMQ 服務也不會處於崩潰的狀態,不過部分操作會受影響,比如不能創建隊列、交換器、也不能添加用戶及修改用戶權限,更不能添加和刪除集群的節點等功能。
注意:對於 RabbitMQ 集群來說,我們啟動集群節點的順序應該是先啟動磁盤節點再啟動內存節點,而關閉的順序正好和啟動的順序相反,不然可能會導致 RabbitMQ 集群啟動失敗或者是數據丟失等異常問題。
RocketMQ
消息隊列RocketMQ是阿里巴巴集團中間件技術部自主研發的專業消息中間件。產品基於高可用分布式集群技術,提供消息發布訂閱、消息軌跡查詢、定時(延時)消息、資源統計、監控報警等一系列消息雲服務,是企業級互聯網架構的核心產品。
詳細介紹請查看,常見消息隊列--RocketMQ
Redis 輕量級的消息中間件
Redis 是一個高效的內存性數據庫中間件,但使用 Redis 也可以實現消息隊列的功能。
早期的 Redis(Redis 5.0 之前)是不支持消息確認的,那時候我們可以通過 List 數據類型的 lpush 和 rpop 方法來實現隊列消息的存入和讀取功能,或者使用 Redis 提供的發布訂閱(pub/sub)功能來實現消息隊列,但這種模式不支持持久化,List 雖然支持持久化但不能設置復雜的路由規則來匹配多個消息,並且他們二者都不支持消息消費確認。
於是在 Redis 5.0 之后提供了新的數據類型 Stream 解決了消息確認的問題,但它同樣不能提供復雜的路由匹配規則,因此在業務不復雜的場景下可以嘗試性的使用 Redis 提供的消息隊列。
Apache Kafka
大名鼎鼎的 Kafka 是高性能消息隊列的代表,Kafka 是 LinkedIn 開源的一個分布式消息系統,主要使用 Scala 語言開發,已經加入 Apache 頂級項目。
Kafka 集群部署時依賴 ZooKeeper 環境,相比其他的消息隊列,運維成本要高很多,ZooKeeper 的引入,使得 Kafka 可以非常方便地進行水平擴展,支持海量數據的傳輸。
Kafka 的另外一個特點是高吞吐率,在消息持久化寫入磁盤的過程中,使用了多種技術來實現讀寫的高性能,包括磁盤的順序讀寫、零拷貝技術等。