一、問題思考
若有商品系統和搜索系統。我們思考一下,是否存在問題?
- 商品的原始數據保存在數據庫中,增刪改查都在數據庫中完成。
- 搜索服務數據來源是索引庫,如果數據庫商品發生變化,索引庫數據不能及時更新。
- 商品詳情做了頁面靜態化,靜態頁面數據也不會隨著數據庫商品發生變化。
rabbitmq入門、如果我們在后臺修改了商品的價格,搜索頁面和商品詳情頁顯示的依然是舊的價格,這樣顯然不對。該如何解決?
這里有兩種解決方案:
- 方案1:每當后臺對商品做增刪改操作,同時要修改索引庫數據及靜態頁面
- 方案2:搜索服務和商品頁面服務對外提供操作接口,后臺在商品增刪改后,調用接口
?
以上兩種方式都有同一個嚴重問題:就是代碼耦合,后臺服務中需要嵌入搜索和商品頁面服務,違背了微服務的`獨立`原則。
所以,我們會通過另外一種方式來解決這個問題:消息隊列
?
二、什么是消息隊列
消息隊列,即MQ,Message Queue。
消息隊列是典型的:生產者、消費者模型。生產者不斷向消息隊列中生產消息,消費者不斷的從隊列中獲取消息。因為消息的生產和消費都是異步的,而且只關心消息的發送和接收,沒有業務邏輯的侵入,這樣就實現了生產者和消費者的解耦。
結合前面所說的問題:
- 商品服務對商品增刪改以后,無需去操作索引庫或靜態頁面,只是發送一條消息,也不關心消息被誰接收。
- 搜索服務和靜態頁面服務接收消息,分別去處理索引庫和靜態頁面。
如果以后有其它系統也依賴商品服務的數據,同樣監聽消息即可,商品服務無需任何代碼修改。
三、AMQP和JMS
兩者間的區別和聯系:
- JMS是定義了統一的接口,來對消息操作進行統一;AMQP是通過規定協議來統一數據交互的格式
- JMS限定了必須使用Java語言;AMQP只是協議,不規定實現方式,因此是跨語言的。
- JMS規定了兩種消息模型;而AMQP的消息模型更加豐富
四、RabbitMQ的基本原理
如圖所示,生產者產生的消息并不是直接發送給消息隊列Queue的,而是要經過Exchange(交換器),由Exchange再將消息路由到一個或多個Queue,當然這里還會對不符合路由規則的消息進行丟棄掉,這里指的是后續要談到的Exchange Type。那么Exchange是怎樣將消息準確的推送到對應的Queue的呢?那么這里的功勞最大的當屬Binding,RabbitMQ是通過Binding將Exchange和Queue鏈接在一起,這樣Exchange就知道如何將消息準確的推送到Queue中去。
在綁定(Binding)Exchange和Queue的同時,一般會指定一個Binding Key,生產者將消息發送給Exchange的時候,一般會產生一個Routing Key,當Routing Key和Binding Key對應上的時候,消息就會發送到對應的Queue中去。那么Exchange有四種類型,不同的類型有著不同的策略。也就是表明不同的類型將決定綁定的Queue不同,換言之就是說生產者發送了一個消息,Routing Key的規則是A,那么生產者會將Routing Key=A的消息推送到Exchange中,這時候Exchange中會有自己的規則,對應的規則去篩選生產者發來的消息,如果能夠對應上Exchange的內部規則就將消息推送到對應的Queue中去。
Exchange(交換器):用于把消息路由到隊列的組件。
Producer(生產者)
會將消息發送給Exchange(交換器)
,由Exchange(交換器)
將消息路由到一個或者多個Queue(隊列)
(或者丟棄)。因為消息是存儲在Queue(隊列)
中,所以Exchange(交換器)
的使用并不真正的消耗服務器的性能,而Queue(隊列)
會。
Queue(隊列):用于存儲消息的數據結構(內存或者硬盤)。
1、Queue(隊列)是RabbitMQ的內部對象,用于存儲消息。RabbitMQ中的消息都只能存儲在Queue(隊列)中。
2、多個Consumer(消費者)可以訂閱同一個Queue(隊列),此時隊列中的消息會被平均分配(Round-Robin,輪詢)給多個Consumer(消費者)處理,RabbitMQ不支持隊列層面的廣播消費。
Binding(綁定規則):一套規則,用于告訴Exchange(交換器)
消息應該被存儲到哪個Queue(隊列)。
?
1、RoutingKey(路由鍵): Producer將消息發送給Exchange(交換器)時一般會指定一個RoutingKey(路由鍵)用來指定這個消息的路由規則,而這個RoutingKey(路由鍵)需要與交換器類型、BindingKey(綁定鍵)聯合使用,最終才能到相應的Queue(隊列)
2、?BindingKey(綁定鍵):RabbitMQ Broker通過BindingKey(綁定鍵)將Exchange(交換器)與Queue(隊列)關聯起來,這樣RabbitMQ Broker就知道如何正確地將消息路由到那個Queue(隊列)了
3、?當RoutingKey(路由鍵)與BindingKey(綁定鍵)相匹配時,消息會被路由到對應的隊列中。在綁定多個隊列到同一個Exchange(交換器)的時候,這些綁定允許使用相同的BindingKey(綁定鍵),BindingKey(綁定鍵)是否有效取決于Exchange(交換器)的類型,比如fanout類型的Exchange(交換器)無論BindingKey(綁定鍵)是什么都會將消息路由到所有綁定到該Exchange(交換器)的Queue(隊列)中。
?