消息中間件對目前大中型互聯網來講是很是重要的,在業務數據流動中僅次於RPC服務調用,擔負着愈來愈複雜的網站業務從主流程上解耦的重要責任;
從目前互聯網對消息中間件的需求來看應該分爲兩種類型,一種是和錢相關的需求,一種是和錢無關的需求;和錢相關的需求消息的可靠性是放在第一位的,和錢無關的需求是速度放在第一位的,但這兩種需求又是矛盾的,很難設計出一種既可靠又高效的系統,除非將兩套方案捏合成一個系統,經過配置來選擇不一樣方案,但從實現上說仍是兩種實現。因此目前業界有幾種不一樣的設計方式來知足不一樣的需求。
下面看看如下幾種典型實現方案:
一、以ActiveMQ爲表明的可靠性優先的設計原理:
此種方案將全部的消息數據和消息的發送狀態都存儲在消息服務器上,能夠在消息服務上經過多種手段來保證消息的可靠性,但增長了衆多複雜的可靠性保證手段後,消息從發佈者到訂閱者的速度勢必會受到影響;此種方式發佈者將消息推向消息服務器,消息服務器再將消息推向訂閱者,爲消息發送策略提供了很好的可擴展性;
二、以KafKa爲表明的速度優先的設計原理:
此種方式將消息的發送狀態保存在客戶端,同時客戶端用拉的模式從消息服務器上獲取消息,因爲是順序讀,同時還採起了不少保證速度的策略,如zero-copy,因此此種方案速度比較快,但犧牲了不少可靠性方面的保證,比較適合Web2.0網站,這些網站對消息的可靠性要求不是很高,同時因爲產生了大量的和用戶狀態相關的消息,須要一個高效的系統來處理這些消息;另外這種方案也比較適合日誌消息的收集;
三、傳統的系解耦方案:
此種方式是不用消息中間件直接用數據庫存儲作的解耦,隨着消息中間件的出現,這種方式的使用愈來愈少,但如今因爲MongoDB和Redis等的興起,一些基於這些Nosql數據庫的消息應用逐漸興起,因爲消息數據和消息狀態都存儲在DB上,因此效率和速度在上面兩種方案之間;sql
那麼有沒有一種更高效的方式呢?數據庫
答案是確定的,但那可能要進一步下降可靠性!服務器
看看Facebook的Scribe日誌收集系統的原理:網絡
若是Scribe Server正常工做,Scribe Client將App的日誌(能夠當作一個消息)推送到Scribe Server端,若是不正常,則寫到本地文件,當Scribe Server恢復正常時再將其推送過去;這裏使用本地文件做爲緩衝,那麼可否綜合Scribe和Kafka的優勢來設計一個消息系統(或日誌收集系統,改造一下能夠互用),看下面的方案:網站
上面的MQ暫且叫他FastMQ吧,①中消息發佈端直接寫本地文件,同時消息訂閱者經過Zookeeper協調,向相關消息發佈者的Agent拉消息,並在本地記錄消息指針狀態;設計
若是嫌在消息發佈端開啓MQ Agent麻煩,那麼如②中消息拉取協議使用SCP或FTP協議,用這些Linux必備的協議提供者做爲Agent減小開發和部署的難度,在服務訂閱端解析這些協議流,反序列化爲消息供業務使用;指針
若是以爲消息只存儲在消息發佈端的磁盤不可靠,那麼如③中能夠在消息訂閱者處理不及消息的時候,把消息數據緩衝在消息訂閱端的磁盤上來備份數據,不過這樣作就使系統變的複雜,雖然提升了可靠性,可是速度就會有所下降;日誌
此種方案可使消息分散的存儲在業務自己的磁盤上,避免集中存儲相互影響的缺點,同時又能夠有效利用業務機器的磁盤(大部分業務機器磁盤基本沒使用),另外還能夠減小一次網絡通訊的過程,使從發送到接收的速度更快;但其自己也有很多缺點,要作好監控,避免消息大量積壓的時候業務磁盤過分使用,對業務形成影響。中間件
目前咱們的監控日誌收集系統使用的是和②中相似的方案,消息系統使用的是3方案,後期可能會將可靠性要求高的向1方案過分,可靠性要求不高的向最下面介紹這種過分!圖片
轉自:http://www.iteye.com/topic/1113331