可伸縮性最佳實踐

這一篇是可伸縮性的最佳實踐,我自己也說了說自己的理解。

異步

 同步調用使得組件和組件之間緊密耦合起來,這樣就使得要想伸縮應用就需要伸縮所有的組件,這不僅帶來使得伸縮的成本增加,而且這種高度耦合性使得伸縮變得更加困難。因此我們需要從應用角度劃分出,哪些業務操作是緊密關聯的,哪些是可以異步執行的,劃分出那些可以異步執行的操作,然後將其進行異步化處理(比如通過JMS,事件隊列,多播消息等或者線程池等),這樣劃分的好處就是系統可以應對更大的訪問量,消弱訪問峯值,比如在同步的時候A調用了B,那麼用戶能接受響應時間就是A處理時間+B處理的時間,而採用異步以後,當訪問量增大的時候,因爲AB異步,那麼A很快返回,用戶體會不到延遲,而B的處理時間由原來的2秒處理完畢,變爲3秒處理完畢,而B得處理都是在後臺進行的,不會影響到客戶響應事件,同時異步也起到了消弱峯值的作用。
 其實在社會生活中也存在很多異步的場景,比如老闆和祕書,假如老闆沒有祕書,那麼勢必老闆在處理完事情A之前沒有辦法處理新的事務,而有了祕書以後,有什麼次要的事情讓祕書去辦,同時老闆可以做其它的重要的事情O(_)
因此異步不僅利用底層框架平臺的異步性,更重要的是如何做到應用本身的異步性,只有做到了這一點纔算是真正的異步。

泳道設計

通過泳道(非常形象的比喻)將錯誤進行隔離,使得不同的錯誤域的錯誤不會相互干擾,這樣也就不會因爲系統某一部分的錯誤影響到系統的其它的部分。

緩存

在系統多個層使用緩存,比如在數據庫前面的Model緩存,頁面,頁面片段緩存等。

監控

我們應該站在真正用戶的角度去理解系統的性能,包括從外部網絡測試用戶體驗以及內部系統的各個組件調用的次數以及每次調用的時間等等。

複製

數據庫讀寫庫分離,這樣不僅可以做到一定的容災,而且可以通過讀寫分離來減低寫數據庫的壓力。

切分

沒有切分就沒有伸縮性,因此一個具有良好伸縮性的系統必須進行切分,而切分可以從兩個地方入手,首先應用角度來說,可以將系統在垂直方向上面分層(這是一種系統架構級的粗粒度的切分),同時將系統的每個層按照功能或者資源進行水平的切分(這是一種相對細粒度的應用級的切分)。
其次對於數據的切分,比如將用戶信息,交易信息,商品信息等獨立存儲,數據庫的切分主要有讀寫庫分離以及Sharding技術。

儘量少用關係數據庫特性

系統使用關係數據庫的特性越多,那麼伸縮性就會變得越差,這就要求將應用邏輯從數據庫真正的移動到應用中來,數據庫僅僅是一種存儲的技術手段,而不是應用邏輯運算的地方。
 我想這一點大家應該比較清楚,如果將業務邏輯用存儲過程實現,那麼就會造成非常差的伸縮性,但是我想說的是及時不用關係數據庫的特性,如果我們不能從應用的角度去設計系統,照樣會造成很差的伸縮性。比如目前普遍採用的SSH,其實說白了這還是一種面向過程的開發,每次業務操作都是從Dao獲取數據,然後Service改變一些數據,最終調用Dao保存數據,這種方式還是一種沒有伸縮性的方案。
 那麼什麼樣的方式比較具有伸縮性,我個人認爲通過領域建模和分佈式緩存,通過對象建模形成業務對新,業務對象以聚合的方式存在緩存中(當然隨着KEY-VALUE的不斷流行,我們可以直接將聚合跟存放在KEY-VALUE存儲系統中),每次業務操作都是存緩存中取出業務對象,調用業務對象進行業務操作,操作的過程中,業務對象會觸發領域事件,然後最終領域事件監聽器調用技術組件完成一些附加操作,採用這種方式,我們還可以採用異步的領域事件,這就使得系統的併發通過JAVA本身的內存鎖機制實現,而不是靠原來的數據庫的事務隔離性來保證併發安全性。

壓力和性能測試

在系統發佈前進行壓力和性能測試,儘管不會發現所有隱藏的問題,但是它也是非常值得的。

容量規劃以及伸縮性探討會

我們要清楚的認識到當前系統能支持的負載,以及系統中可能存在的性能和伸縮性的瓶頸在哪裏,在解決了某一個伸縮性的瓶頸以後,我們就需要關注下一個隨着系統不斷增加可能帶來伸縮性瓶頸的問題。
 

回滾

任何操作都有可能失敗,因此我們的系統一定要做好回滾操作,這個回滾操作室廣義的回滾,具體可參考“可伸縮性和可用性反模式”。

根源分析

確保能在發生問題的時候找到問題的根源,做到治標治本。

關注系統質量

應該在系統開始的時候就關注系統質量,而不是在測試階段出現問題的時候才考慮如何伸縮,那個時候就晚了。
 
 
原文:
 
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章