我們知道在物件導向程式設計中,總會想著各種辦法來實現程式碼的解耦,從而讓專案中的各種人員面對自己熟悉的業務進行開發,
做到術業有專攻,比如大家非常熟悉的三層架構,MVC,MVP以及MVVM模式,讓前端設計專注於html的製作,讓後端開發人員
更加專注於業務邏輯的編寫,可以看到,我們這麼做的目的就是想最大程度的做到系統的可擴充套件和可維護性,那麼我們的大型網站
是不是也要遵守這種模式呢?
一:分層和分割
1:分層
對於分層,我們可能非常熟知了,資料訪問層,業務邏輯層,快取層,應用層,層層專注於自己的業務,然後根據需要建立起
各自的叢集,各自分離部署,而從達到系統的擴充套件性和維護性。
2:分割
如果說前面是橫向切割,那分割就是縱向切割,我們可以把網站的整體業務切分成很多的小業務,比如部落格園的導航欄,我們都
可以認為是一個獨立的網站,配上各自的二級域名,建立各自的叢集來實現系統的擴充套件性,當然這個粒度可大可小。
如果說這些子網站不存在相互呼叫,那麼我們新增模組或者修改模組基本上都不會對其他模組造成影響,這也是我們做擴充套件性的終極
目標,現在既然都做到解耦了,下面的目標就是做如何通訊了,通訊可以分為“同步”和“非同步”,這篇主要是討論下非同步操作,在分散式
系統中做到"非同步操作“,當然少不了強大的訊息佇列。
二:訊息佇列
在分散式的系統中使用訊息佇列後,我們的生產者只管向訊息佇列中甩完資料後立即返回,而不管是哪個消費者來消費,可以看到
其實訊息佇列有如下三個優點。
1. 加快網站的相應速度
這個剛才也說了,應用層直接把訊息給訊息佇列然後直接返回撥用端,這樣就避免了處理複雜的業務邏輯然後同步的插入到資料
庫後再返回造成的響應延遲,在很多網站上使用者提交訂單就是這麼處理的,應用層生成一個訂單號之後,將訂單丟給訊息佇列,然後
直接到訂單成功頁面,此時後端消費者對訂單還沒有處理完畢,因為後面會有比較多的資料操作,比如減庫存,資料庫同步等等,而
使用者如果想要看到訂單詳情,需要點選“訂單號”才能進入到訂單詳情頁,這種處理也是因為訊息佇列的非及時性,所以需要得到網站
設計方改進和支援。
2. 提供系統的可用性
既然是非同步操作,就造成了生產者不知道消費者的存在,而反過來消費者不知道生產者的存在,如果消費者掛了就不會影響到生產者,
生產者還會照常無誤的向訊息佇列甩訊息,當消費者恢復正常後就會繼續消費訊息佇列,系統的表現可能就是email或者簡訊延遲收到,
不會對系統造成太大的影響。
3. 併發削峰
既然是大型網站就免不了高併發的讀寫操作,很典型的一個例子就是電商中的秒殺,這種高併發的寫操作,如果一下子都湧入到資料庫
裡面去了,會導致資料庫的壓力非常大,從而導致客戶端的訪問延遲,就是不掛也容易造成資料庫的死鎖從而造成很多靈異事件,遇到這
種一擁而入的情況,我們就必須進行線性化操作,在程式碼層面上我們可以用lock機制來序列化,在分散式中我們用“訊息佇列”來序列化,
而且還可以通過邏輯操作來對訊息佇列進行動態的防洪,控洪。
在訊息佇列的選擇上,微軟有自己的MSMQ,但是在大型網站中,我們的訊息佇列同樣需要叢集,並且希望能跑在記憶體中,並且支援序列
化硬碟,同時在“伸縮性”和“可靠性”上要有好的作為,所以推薦大家用用開源的RabbitMQ,網址:http://www.rabbitmq.com/ 不過很
多公司都有自己開發的訊息佇列,比如攜程的CMessage,淘寶的MetaQ。