1. 概述
消息隊列中間件是分布式系統(tǒng)中重要的組件,主要解決應用耦合给梅、異步消息假丧、流量削鋒等問題。實現(xiàn)高性能动羽、高可用包帚、可伸縮和最終一致性架構。是大型分布式系統(tǒng)不可缺少的中間件运吓。
目前在生產環(huán)境婴噩,使用較多的消息隊列有ActiveMQ、RabbitMQ羽德、ZeroMQ、Kafka迅办、MetaMQ宅静、RocketMQ等。
應用場景分為異步處理站欺、應用解耦姨夹、流量削鋒和消息通訊四個場景。
異步處理
場景說明:用戶注冊后矾策,需要發(fā)送注冊郵件和發(fā)送注冊信息磷账,傳統(tǒng)的做法有兩種:串行方式、并行方式
-
串行方式
將注冊信息寫入數(shù)據(jù)庫成功后贾虽,發(fā)送注冊郵件逃糟,然后發(fā)送注冊短信,而所有任務執(zhí)行完成后,返回信息給客戶端
-
并行方式
將注冊信息寫入數(shù)據(jù)庫成功后绰咽,同時進行發(fā)送注冊郵件和發(fā)送注冊短信的操作菇肃。而所有任務執(zhí)行完成后,返回信息給客戶端取募。同串行方式相比琐谤,并行方式可以提高執(zhí)行效率,減少執(zhí)行時間玩敏。
上面的比較可以發(fā)現(xiàn)斗忌,假設三個操作均需要50ms的執(zhí)行時間,排除網絡因素旺聚,則最終執(zhí)行完成织阳,串行方式需要150ms,而并行方式需要100ms翻屈。
因為cpu在單位時間內處理的請求數(shù)量是一致的陈哑,假設:CPU每1秒吞吐量是100此,則串行方式1秒內可執(zhí)行的請求量為1000/150伸眶,不到7次惊窖;并行方式1秒內可執(zhí)行的請求量為1000/100,為10次厘贼。
由上可以看出界酒,傳統(tǒng)串行和并行的方式會受到系統(tǒng)性能的局限,那么如何解決這個問題嘴秸?
我們需要引入消息隊列毁欣,將不是必須的業(yè)務邏輯,異步進行處理岳掐,由此改造出來的流程為:
根據(jù)上述的流程凭疮,用戶的響應時間基本相當于將用戶數(shù)據(jù)寫入數(shù)據(jù)庫的時間,發(fā)送注冊郵件串述、發(fā)送注冊短信的消息在寫入消息隊列后执解,即可返回執(zhí)行結果,寫入消息隊列的時間很快纲酗,幾乎可以忽略衰腌,也有此可以將系統(tǒng)吞吐量提升至20QPS,比串行方式提升近3倍觅赊,比并行方式提升2倍右蕊。
應用解耦
場景說明:用戶下單后,訂單系統(tǒng)需要通知庫存系統(tǒng)吮螺。
傳統(tǒng)的做法為:訂單系統(tǒng)調用庫存系統(tǒng)的接口饶囚。如下圖所示:
傳統(tǒng)方式具有如下缺點:
-1. 假設庫存系統(tǒng)訪問失敗帕翻,則訂單減少庫存失敗,導致訂單創(chuàng)建失敗
-2. 訂單系統(tǒng)同庫存系統(tǒng)過度耦合
訂單系統(tǒng):用戶下單后坯约,訂單系統(tǒng)進行數(shù)據(jù)持久化處理熊咽,然后將消息寫入消息隊列,返回訂單創(chuàng)建成功
庫存系統(tǒng):使用拉/推的方式闹丐,獲取下單信息横殴,庫存系統(tǒng)根據(jù)訂單信息,進行庫存操作卿拴。
假如在下單時庫存系統(tǒng)不能正常使用衫仑。也不影響正常下單,因為下單后堕花,訂單系統(tǒng)寫入消息隊列就不再關心其后續(xù)操作了文狱。由此實現(xiàn)了訂單系統(tǒng)與庫存系統(tǒng)的應用解耦。
流量削鋒
流量削鋒也是消息隊列中的常用場景缘挽,一般在秒殺或團搶活動中使用廣泛瞄崇。
應用場景:秒殺活動,一般會因為流量過大壕曼,導致流量暴增苏研,應用掛掉。為解決這個問題腮郊,一般需要在應用前端加入消息隊列摹蘑。
- 可以控制參與活動的人數(shù);
-
可以緩解短時間內高流量對應用的巨大壓力轧飞;
流量削鋒處理方式系統(tǒng)圖如下:
1.服務器在接收到用戶請求后衅鹿,首先寫入消息隊列。這時如果消息隊列中消息數(shù)量超過最大數(shù)量过咬,則直接拒絕用戶請求或返回跳轉到錯誤頁面大渤;
- 秒殺業(yè)務根據(jù)秒殺規(guī)則讀取消息隊列中的請求信息,進行后續(xù)處理掸绞。
日志處理
日志處理是指將消息隊列用在日志處理中泵三,比如Kafka的應用,解決大量日志傳輸?shù)膯栴}集漾。架構簡化如下
1.日志采集客戶端:負責日志數(shù)據(jù)采集,定時寫受寫入Kafka隊列砸脊;
2.Kafka消息隊列:負責日志數(shù)據(jù)的接收具篇,存儲和轉發(fā);
3.日志處理應用:訂閱并消費kafka隊列中的日志數(shù)據(jù)凌埂;
消息通訊
消息通訊是指驱显,消息隊列一般都內置了高效的通信機制,因此也可以用在純的消息通訊。比如實現(xiàn)點對點消息隊列埃疫、聊天室等伏恐。
在點對點通訊架構設計中,客戶端A和客戶端B共用一個消息隊列栓霜,即可實現(xiàn)消息通訊功能翠桦。
客戶端A、客戶端B胳蛮、直至客戶端N訂閱同一消息隊列销凑,進行消息的發(fā)布與接收,即可實現(xiàn)聊天通訊方案架構設計仅炊。
常用消息隊列
1.RocketMQ
阿里系下開源的一款分布式斗幼、隊列模型的消息中間件,原名Metaq抚垄,3.0版本名稱改為RocketMQ蜕窿,是阿里參照kafka設計思想使用java實現(xiàn)的一套mq。同時將阿里系內部多款mq產品(Notify呆馁、metaq)進行整合桐经,只維護核心功能,去除了所有其他運行時依賴智哀,保證核心功能最簡化次询,在此基礎上配合阿里上述其他開源產品實現(xiàn)不同場景下mq的架構,目前主要多用于訂單交易系統(tǒng)瓷叫。
2.ActiveMQ
Apache下的一個子項目屯吊。使用Java完全支持JMS1.1和J2EE 1.4規(guī)范的 JMS Provider實現(xiàn),少量代碼就可以高效地實現(xiàn)高級應用場景摹菠『行叮可插拔的傳輸協(xié)議支持,比如:in-VM, TCP, SSL, NIO, UDP, multicast, JGroups and JXTA transports次氨。RabbitMQ蔽介、ZeroMQ、ActiveMQ均支持常用的多種語言客戶端 C++煮寡、Java虹蓄、.Net,、Python幸撕、 Php薇组、 Ruby等。
- Redis
使用C語言開發(fā)的一個Key-Value的NoSQL數(shù)據(jù)庫坐儿,開發(fā)維護很活躍律胀,雖然它是一個Key-Value數(shù)據(jù)庫存儲系統(tǒng)宋光,但它本身支持MQ功能,所以完全可以當做一個輕量級的隊列服務來使用炭菌。對于RabbitMQ和Redis的入隊和出隊操作罪佳,各執(zhí)行100萬次,每10萬次記錄一次執(zhí)行時間黑低。測試數(shù)據(jù)分為128Bytes赘艳、512Bytes、1K和10K四個不同大小的數(shù)據(jù)投储。實驗表明:入隊時第练,當數(shù)據(jù)比較小時Redis的性能要高于RabbitMQ,而如果數(shù)據(jù)大小超過了10K玛荞,Redis則慢的無法忍受娇掏;出隊時,無論數(shù)據(jù)大小勋眯,Redis都表現(xiàn)出非常好的性能婴梧,而RabbitMQ的出隊性能則遠低于Redis。
4.RabbitMQ
RabbitMQ是流行的開源消息隊列系統(tǒng)客蹋,用erlang語言開發(fā)塞蹭。RabbitMQ是AMQP(高級消息隊列協(xié)議)的標準實現(xiàn)。支持多種客戶端讶坯,如:Python番电、Ruby、.NET辆琅、Java漱办、JMS、C婉烟、PHP娩井、ActionScript、XMPP似袁、STOMP等洞辣,支持AJAX,持久化昙衅。用于在分布式系統(tǒng)中存儲轉發(fā)消息扬霜,在易用性、擴展性而涉、高可用性等方面表現(xiàn)不俗著瓶。
Kafka
Apache下的一個子項目,使用scala實現(xiàn)的一個高性能分布式Publish/Subscribe消息隊列系統(tǒng)婴谱。ZeroMQ
號稱最快的消息隊列系統(tǒng)蟹但,專門為高吞吐量/低延遲的場景開發(fā),在金融界的應用中經常使用谭羔,偏重于實時數(shù)據(jù)通信場景华糖。ZMQ能夠實現(xiàn)RabbitMQ不擅長的高級/復雜的隊列,但是開發(fā)人員需要自己組合多種技術框架瘟裸,開發(fā)成本高客叉。因此ZeroMQ具有一個獨特的非中間件的模式,更像一個socket library话告,你不需要安裝和運行一個消息服務器或中間件兼搏,因為你的應用程序本身就是使用ZeroMQ API完成邏輯服務的角色。但是ZeroMQ僅提供非持久性的隊列沙郭,如果down機佛呻,數(shù)據(jù)將會丟失。如:Twitter的Storm中使用ZeroMQ作為數(shù)據(jù)流的傳輸病线。
ZeroMQ套接字是與傳輸層無關的:ZeroMQ套接字對所有傳輸層協(xié)議定義了統(tǒng)一的API接口吓著。默認支持 進程內(inproc) ,進程間(IPC) 送挑,多播绑莺,TCP協(xié)議,在不同的協(xié)議之間切換只要簡單的改變連接字符串的前綴惕耕》牟茫可以在任何時候以最小的代價從進程間的本地通信切換到分布式下的TCP通信。ZeroMQ在背后處理連接建立司澎,斷開和重連邏輯欺缘。