MQ簡介
消息隊列
在認識rabbitMQ之前,我們需要先認識下消息隊列。
消息隊列,一般簡稱為MQ(Message Queue)。先不管消息(Message)這個詞,先看看隊列(Queue)。
隊列就是一種先進先出的數據結構。
所以消息隊列可以簡單理解為:把要傳輸的數據放在隊列中。
科普:
- 把數據放到消息隊列叫做生產者
- 從消息隊列里邊取數據叫做消費者
為什么要用MQ
MQ可通過消息的收發,使多個系統之間不局限於同步調用,通過異步調用更好地實現解耦,流量削峰等。下面是幾個常見的應用場景,幫助我們對MQ有一個簡單的認識。
異步處理
引入MQ后,通過異步處理將響應時間減少至原先的1/3
應用解耦
場景:雙11是購物狂節,用戶下單后,訂單系統需要通知庫存系統,傳統的做法就是訂單系統調用庫存系統的接口
缺點:
- 當庫存系統出現故障時,訂單就會失敗。(這樣馬雲將少賺好多好多錢^ ^)
- 訂單系統和庫存系統高耦合.
引入消息隊列后:
- 訂單系統:用戶下單后,訂單系統完成持久化處理,將消息寫入消息隊列,返回用戶訂單下單成功
- 庫存系統:訂閱下單的消息,獲取下單消息,進行庫操作。就算庫存系統出現故障,消息隊列也能保證消息的可靠投遞,不會導致消息丟失(馬雲這下高興了).
流量削峰
流量削峰一般在秒殺活動中應用廣泛
場景:秒殺活動,一般會因為流量過大,導致應用掛掉。比如業務系統每秒只能處理1000個請求,但是一下子來了5000個請求,那系統就崩了。為了解決這個問題,一般會將用戶請求加入消息隊列。
引入消息隊列后:
1.用戶的請求,服務器收到之后,首先寫入消息隊列,加入消息隊列長度超過最大值,則直接拋棄用戶請求或跳轉到錯誤頁面.
2.秒殺業務根據消息隊列中的請求信息,再做后續處理。避免系統崩潰。
使用MQ要考慮什么問題
熟悉后端編程的同學都知道,python,java都有自己的隊列函數。比如python的Queue.LifoQueue,Queue.PriorityQueue 。那為啥還要用RabbitMQ這種消息隊列中間件呢?
1.高可用
無論是我們使用消息隊列來做解耦、異步還是削峰,消息隊列肯定不能是單機的。萬一這台機器掛了,那我們整個系統幾乎就是不可用了。所以,當我們項目中使用消息隊列,都是得集群/分布式的。要做集群/分布式就必然希望該消息隊列能夠提供現成的支持,而不是自己寫代碼手動去實現。
2. 數據丟失問題
A系統將數據寫到消息隊列上,系統B和C還沒來得及取消息隊列的數據,就掛掉了。如果沒有做任何的措施,我們的數據就丟了。
3.消費者怎么得到消息隊列的消息
兩種方法:
-
生產者將數據放到消息隊列中,消息隊列有數據了,主動叫消費者去拿(俗稱push)
-
消費者不斷去輪訓消息隊列,看看有沒有新的數據,如果有就消費(俗稱pull)
4.其他
除了這些,我們在使用的時候還得考慮各種的問題:
- 消息重復消費了怎么辦啊?
- 我想保證消息是絕對有順序的怎么做?
- ……..
基於這些問題,市面上涌現了很多消息隊列的中間件。這些MQ中間件幾乎都解決了上面的問題,但也存在差異。
常見的MQ產品
這里有一個簡介:
- ActiveMQ:基於JMS,Apache
- RocketMQ:(Rocket,火箭)阿里巴巴的產品,基於JMS,目前由Apache維護
- Kafka:分布式消息系統,亮點:吞吐量超級高,每秒中數十萬的並發。
- RabbitMQ:由erlang語言開發,基於AMQP協議,在erlang語言特性的加持下,RabbitMQ穩定性要比其他的MQ產品好一些,而且erlang語言本身是面向高並發的編程的語言,所以RabbitMQ速度也非常快。且它基於AMQP協議,對分布式、微服務更友好。
科普:
AMQP協議:即Advanced Message Queuing Protocol,是一個應用層標准高級消息隊列協議,提供統一消息服務。是應用層協議的一個開放標准,為面向消息的中間件設計。基於此協議的客戶端與消息中間件可傳遞消息,並不受客戶端/中間件不同產品,不同的開發語言等條件的限制。
JMS:即Java消息服務(Java Message Service)應用程序接口,由sun公司提出,並且sun公司定義好了接口。包括create、send、recieve。只要想使用它,就得實現它定義的接口。 消息服務是一個與具體平台無關的API,絕大多數MOM提供商都對JMS提供支持。不好的地方是語言層面的限制,只能為JAVA,這其實稍微有點和微服務的觀點相違背。要求語言只能是JAVA,而不能是py等。(沒明白最后一句啥意思--||)