本文將主要介紹系統(tǒng)設(shè)計(jì)中的異步執(zhí)行和消息隊(duì)列。這里假設(shè)讀者已經(jīng)有了一部分這方面的知識(shí),一些概念的介紹不會(huì)過于深入,而會(huì)將重點(diǎn)放在各種實(shí)現(xiàn)方式的優(yōu)劣比較上。
異步執(zhí)行
客戶端和服務(wù)器端的交互方式通常有兩種:同步執(zhí)行和異步執(zhí)行。其中互聯(lián)網(wǎng)應(yīng)用普遍采用的是異步執(zhí)行,異步執(zhí)行可以極大的提高系統(tǒng)的處理能力。
以下為兩種交互方法的示意圖:


不要使用數(shù)據(jù)庫
采用異步執(zhí)行的方式,需要至少在客戶端維護(hù)一個(gè)消息列表,接收由客戶端發(fā)送來的消息。這個(gè)消息列表很容易的可以想到由數(shù)據(jù)庫來實(shí)現(xiàn),在數(shù)據(jù)庫中記錄每條消息本身及其狀態(tài),服務(wù)器端從數(shù)據(jù)庫中獲取待執(zhí)行的任務(wù)并執(zhí)行,同時(shí)進(jìn)行消息的狀態(tài)的更新。
但我們說,數(shù)據(jù)庫并不適合異步處理的場景。原因有以下三點(diǎn):
需要頻繁讀數(shù)據(jù)庫。服務(wù)器端需要以一個(gè)固定的時(shí)間間隔,不斷從數(shù)據(jù)庫中獲取新的消息。如果間隔設(shè)置的很小,將在數(shù)據(jù)庫中產(chǎn)生大量的查詢請(qǐng)求,會(huì)影響數(shù)據(jù)庫對(duì)寫入和更新的處理;如果間隔設(shè)置的較大,會(huì)給異步執(zhí)行帶來一定的處理延遲,對(duì)延遲敏感的系統(tǒng)來說是影響很大的。
手動(dòng)清理。對(duì)于已經(jīng)處理過的消息,是需要清理掉的。因此又需要定期對(duì)數(shù)據(jù)庫進(jìn)行刪除操作,增加了數(shù)據(jù)庫的負(fù)擔(dān)。
可擴(kuò)展性不佳。如果消息量過大,數(shù)據(jù)庫性能下降時(shí),擴(kuò)展的工作將會(huì)很復(fù)雜。
需要特殊注意的是,PostgreSQL是提供對(duì)異步執(zhí)行的支持的,也是通過消息隊(duì)列的方式,因此對(duì)于少量或中等的消息量來說,是可以用PostgreSQL的。
消息隊(duì)列
消息隊(duì)列是連接消息發(fā)送方和消費(fèi)方的中間件,它的幾個(gè)特點(diǎn)是:
- 可以處理海量的并發(fā)消息;
- 消息通知采用推送的方式,而不是定期拉取的方式;
- 消息持久化,服務(wù)中斷時(shí)消息不會(huì)丟失;
- 過期消息會(huì)自動(dòng)清理;
- 不用擔(dān)心死鎖和競態(tài)的問題。

消息隊(duì)列的一大特點(diǎn)是消息的拓?fù)浣Y(jié)構(gòu)可以任意設(shè)計(jì),比如一個(gè)topic可以對(duì)應(yīng)1個(gè)consumer,或多個(gè)consumer,如下圖所示。

消息隊(duì)列協(xié)議
消息隊(duì)列協(xié)議,隨著協(xié)議的發(fā)展出現(xiàn)了很多,比如STOMP、AMQP、JMS等,其中AMQP是出現(xiàn)的比較晚的,相對(duì)技術(shù)更先進(jìn)一些。由于不是本文的重點(diǎn),這里不展開介紹了。

消息隊(duì)列中間件的選擇
目前開源的消息隊(duì)列有RabbitMQ、ActiveMQ等,它們除了協(xié)議不同外,在實(shí)際使用時(shí)并沒有明顯的選擇傾向性。通常來說,ActiveMQ和JVM的結(jié)合性更高,適合于Java應(yīng)用;RabbitMQ適合于Ruby、Python的應(yīng)用。
消息隊(duì)列除了做系統(tǒng)間的通信外,還可以作為系統(tǒng)內(nèi)部的任務(wù)隊(duì)列,實(shí)現(xiàn)任務(wù)的異步執(zhí)行。此時(shí)選擇哪種消息隊(duì)列,更多的考慮的是消息隊(duì)列的輕量級(jí)、易使用和易維護(hù)等方面。
小結(jié)
本文介紹了在異步執(zhí)行中進(jìn)行消息通信的方式,使用數(shù)據(jù)庫的方式在許多場景并不是最好的,但在一些消息量小的情況也是可以使用的,更通用的做法是使用消息隊(duì)列的方式,消息隊(duì)列本身的特性,為異步執(zhí)行提供了很多支持。
歡迎大家訂閱專題,其中包含了系統(tǒng)設(shè)計(jì)基礎(chǔ)系列的全部文章:System Design
- 參考文獻(xiàn):