分散式架構的演進過程
一個成熟的大型網站架構並不是一開始就設計的非常完美,也不是一開始就具備高效能、高可用、安全性等特性,而是隨著使用者量的增加,業務功能的擴充套件逐步完善演變過來的。在這個過程中,開發模式、技術架構等都會發生非常大的變化。而針對不同業務特徵的系統,會有各自的側重點,比如像淘寶這類的網站,要解決的是海量商品搜尋、下單、支付等問題;騰訊,要解決的是數億級別使用者的實時訊息傳輸;百度所要解決的是海量資料的搜尋。
架構是演變而來的,不是設計出來的。沒有最好的架構,只有最適合的架構。
下面以一個簡單的電商系統為例,當資料量、訪問量提升,觀察這個系統可能會發生的結構變化。假如我們系統具備以下功能:使用者模組(使用者註冊和管理),商品模組(商品展示和管理),交易模組(建立交易及支付結算)。
階段一,單應用架構

網站的初期也可以認為是網際網路發展的早起,我們經常會在單機上跑我們所有的程式和軟體。把所有軟體和應用都部署在一臺機器上,這樣就完成一個簡單系統的搭建,這個時候的講究的是效率。
階段二,應用伺服器和資料庫伺服器分離
隨著網站的上線,訪問量逐步上升,伺服器的負載慢慢提高,在伺服器還沒有超載的時候,我們應該做好規劃,提升網站的負載能力。假如程式碼層面的優化已經沒辦法繼續提高,在不提高單臺機器的效能,增加機器是一個比較好的方式,投入產出比非常高。這個階段增加機器的主要目的是將web 伺服器和資料庫伺服器拆分,這樣不僅提高了單機的負載能力,也提高了容災能力。

階段三,應用伺服器叢集
隨著訪問量的繼續增加,單臺應用伺服器已經無法滿足需求。在假設資料庫伺服器還沒有遇到效能問題的時候,我們可以增加應用伺服器,通過應用伺服器叢集將使用者請求分流到各個伺服器中,從而繼續提升負載能力。此時多臺應用伺服器之間沒有直接的互動,他們都是依賴資料庫各自對外提供服務。

架構發展到這個階段,各種問題也會慢慢呈現,比如使用者請求由誰來轉發到具體的應用伺服器,這時候可能會出現下面的架構模型。

階段四,資料庫讀寫分離
當資料庫壓力變大時,那麼怎麼去提高資料庫層面的負載呢?有了前面的思路以後,自然會想到增加伺服器。但是假如我們單純的把資料庫一分為二,然後對於後續資料庫的請求,分別負載到兩臺資料庫伺服器上,那麼一定會造成資料庫不統一的問題。所以我們一般先考慮讀寫分離的方式。

階段五,使用搜索引擎緩解讀庫的壓力
資料庫做讀庫的話,常常對模糊查詢效率不是特別好,像電商類的網站,搜尋是非常核心的功能,即便是做了讀寫分離,這個問題也不能有效解決。那麼這個時候可以引入搜尋引擎,使用搜索引擎能夠大大提高我們的查詢速度。

階段六,引入快取機制緩解資料庫的壓力
隨著訪問量的持續增加,逐漸出現許多使用者訪問同一部分內容的情況。對於這些熱點資料,沒必要每次都從資料庫去讀取,我們可以使用快取技術,比如memcache、redis 來作為我們應用層的快取;另外在某些場景下,比如我們對使用者的某些IP 的訪問頻率做限制,那這個放記憶體中又不合適,放資料庫又太麻煩,這個時候可以使用Nosql 的方式比如mongDB 來代替傳統的關係型資料庫。

階段七,資料庫的水平/垂直拆分
我們的網站演進的變化過程,交易、商品、使用者的資料都還在同一個資料庫中,儘管採取了增加快取,讀寫分離的方式,但是隨著資料庫的壓力持續增加,資料庫的瓶頸仍然是個最大的問題。因此我們可以考慮對資料的垂直拆分和水平拆分。
垂直拆分:把資料庫中不同業務資料拆分到不同的資料庫。
水平拆分:把同一個表中的資料拆分到兩個甚至更多的表中。

階段八,應用的拆分
隨著業務的發展,業務越來越多,應用的壓力越來越大,工程規模也越來越龐大。這個時候就可以考慮將應用拆分,按照領域模型將系統拆成使用者、商品、交易子系統。

這樣拆分以後,可能會有一些相同的程式碼,比如使用者操作,在商品和交易都需要查詢,所以會導致每個系統都會有使用者查詢訪問相關操作。這些相同的操作一定是要抽象出來,可以通過服務化的方式來解決。
階段九,服務化
服務拆分以後,各個服務之間可以通過RPC 技術進行通訊,比較典型的有:webservice、hessian、http、RMI等。
