消息中間件對目前大中型網際網路來說是非常重要的,在業務資料流動中僅次于RPC服務調用,擔負着越來越複雜的網站業務從主流程上解耦的重要責任;
從目前網際網路對消息中間件的需求來看應該分為兩種類型,一種是和錢相關的需求,一種是和錢無關的需求;和錢相關的需求消息的可靠性是放在第一位的,和錢無關的需求是速度放在第一位的,但這兩種需求又是沖突的,很難設計出一種既可靠又高效的系統,除非将兩套方案捏合成一個系統,通過配置來選擇不同方案,但從實作上說還是兩種實作。是以目前業界有幾種不同的設計方式來滿足不同的需求。
下面看看以下幾種典型實作方案:
1、以ActiveMQ為代表的可靠性優先的設計原理:
此種方案将所有的消息資料和消息的發送狀态都存儲在消息伺服器上,可以在消息服務上通過多種手段來保證消息的可靠性,但增加了衆多複雜的可靠性保證手段後,消息從釋出者到訂閱者的速度勢必會受到影響;此種方式釋出者将消息推向消息伺服器,消息伺服器再将消息推向訂閱者,為消息發送政策提供了很好的可擴充性;
2、以KafKa為代表的速度優先的設計原理:

此種方式将消息的發送狀态儲存在用戶端,同時用戶端用拉的模式從消息伺服器上擷取消息,由于是順序讀,同時還采取了很多保證速度的政策,如zero-copy,是以此種方案速度比較快,但犧牲了很多可靠性方面的保證,比較适合Web2.0網站,這些網站對消息的可靠性要求不是很高,同時由于産生了大量的和使用者狀态相關的消息,需要一個高效的系統來處理這些消息;另外這種方案也比較适合日志消息的收集;
3、傳統的系解耦方案:
此種方式是不用消息中間件直接用資料庫存儲做的解耦,随着消息中間件的出現,這種方式的使用越來越少,但現在由于MongoDB和Redis等的興起,一些基于這些Nosql資料庫的消息應用逐漸興起,由于消息資料和消息狀态都存儲在DB上,是以效率和速度在上面兩種方案之間;
那麼有沒有一種更高效的方式呢?
答案是肯定的,但那可能要進一步降低可靠性!
看看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