閱讀165 返回首頁    go 京東網上商城


如何設計一個牛掰的大型項目架構?

大型電商項目的服務端架構

 

 

我們以淘寶架構為例,了解下大型電商項目的服務端架構是怎樣的,如圖所示:

 

20170504103023347.jpg

 

  • 上麵是一些安全體係係統,如數據安全體係、應用安全體係、前端安全體係等。

  • 中間是業務運營服務係統,如會員服務、商品服務、店鋪服務、交易服務等。

  • 還有共享業務,如分布式數據層、數據分析服務、配置服務、數據搜索服務等。

  • 最下麵是中間件服務,如MQS即隊列服務,OCS即緩存服務等。

 

圖中也有一些看不到,例如高可用的體現、實現雙機房容災和異地機房單元化部署,為淘寶業務提供穩定、高效和易於維護的基礎架構支撐。

 

這是一個含金量非常高的架構,也是一個非常複雜而龐大的架構。當然這個架構不是一天兩天演進而成,也不是一上來就設計並開發成這麼高大上的。

 

這邊我想說的是,小型公司要怎麼做架構呢?對很多創業公司而言,很難在初期就預估到流量十倍、百倍以及千倍以後的網站架構會是一個怎樣的狀況。同時,如果係統初期就設計一個千萬級並發的流量架構,也很難有公司可以支撐這個成本。

 

因此,一個大型服務係統都是從一步一步走過來的,在每個階段,找到對應該階段網站架構所麵臨的問題,然後在不斷解決這些問題,在這個過程中整個架構會一直演進。

 

一、單服務器-俗稱all in one

 

20170504103033825.jpg

 

從一個小網站說起。一台服務器也就足夠了。文件服務器,數據庫,還有應用都部署在一台機器,俗稱ALL IN ONE。

 

隨著我們用戶越來越多,訪問越來越大,硬盤、CPU、內存等都開始吃緊,一台服務器已經滿足不了。這時看到下一步演進。

 

二、數據服務與應用服務分離

 

20170504103042626.jpg

 

我們將數據服務和應用服務分離,給應用服務器配置更好的CPU和內存,給數據服務器配置更好更大的硬盤。

 

分離之後提高一定的可用性,例如Files Server掛了,我們還是可以操作應用和數據庫等。


隨著訪問QPS越來越高,降低接口訪問時間,提高服務性能和並發,成為了我們下一個目標,同時發現有很多業務數據不需要每次都從數據庫獲取。

 

三、使用緩存

 

包括本地緩存、遠程緩存、遠程分布式緩存。

 

20170504103050255.jpg

 

因為 80% 的業務訪問都集中在 20% 的數據上,也就是我們經常說的28法則。如果能將這部分數據緩存下來,性能一下子就上來了。而緩存又分為兩種:本地緩存和遠程緩存緩存,以及遠程分布式緩存,我們這裏麵的遠程緩存圖上畫的是分布式的緩存集群(Cluster)。

 

思考的點

 

  1. 具有哪種業務特點數據使用緩存?

  2. 具有哪種業務特點的數據使用本地緩存?

  3. 具有哪種務特點的數據使用遠程緩存?

  4. 分布式緩存在擴容時會碰到什麼問題?如何解決?分布式緩存的算法都有哪幾種?各有什麼優缺點?

 

這個時候隨著訪問QPS的提高,服務器的處理能力會成為瓶頸。雖然可以通過購買更強大的硬件解決,但總會有上限,而且這個到後期成本就是指數級增長了,這時,我們需要服務器的集群來橫向擴展,所以就必須加個新東西:負載均衡調度服務器。

 

四、使用負載均衡,進行服務器集群

 

20170504103100178.jpg

 

增加了負載均衡、服務器集群之後,我們可以橫向擴展服務器,解決了服務器處理能力的瓶頸。

 

思考的點

 

  1. 負載均衡的調度策略都有哪些?

  2. 各有什麼優缺點?

  3. 各適合什麼場景?

 

打個比方,我們有輪詢、權重、地址散列,地址散列又分為原ip地址散列hash、目標ip地址散列hash,最少連接,加權最少連接,還有繼續升級的很多種策略......我們都來分析一下。


典型負載均衡策略分析

 

  1. 輪詢:優點-實現簡單,缺點-不考慮每台服務器處理能力

  2. 權重:優點-考慮了服務器處理能力的不同

  3. 地址散列:優點-能實現同一個用戶訪問同一個服務器

  4. 最少連接:優點-使集群中各個服務器負載更加均勻

  5. 加權最少連接:在最少連接的基礎上,為每台服務器加上權值。算法為(活動連接數*256+非活動連接數)/權重,計算出來的值小的服務器優先被選擇。

 

繼續引出問題的場景

 

我們登錄時登錄了A服務器,session信息存儲到A服務器上了,假設我們使用的負載均衡策略是ip hash,那麼登錄信息還可以從A服務器上訪問,但這個有可能造成某些服務器壓力過大,某些服務器又沒有什麼壓力,這時壓力過大的機器(包括網卡帶寬)有可能成為瓶頸,並且請求不夠分散。

 

這時候我們使用輪詢或者最小連接負載均衡策略,就導致了第一次訪問A服務器,第二次可能訪問到B服務器,這時存儲在A服務器上的session信息在B服務器上讀取不到。

 

Session管理-Session Sticky粘滯會話

 

20170504103108666.jpg

 

打個比方,如果我們每次吃飯都要保證用的是自己的碗筷,隻要我們在一家飯店裏存著自己的碗筷,並且每次去這家飯店吃飯就好了。

 

對於同一個連接中的數據包,負載均衡會將其轉發至後端固定的服務器進行處理。

 

解決了我們session共享的問題,但是它有什麼缺點呢?

 

  1. 一台服務器運行的服務掛掉,或者重啟,上麵的 session 都沒了。

  2. 負載均衡器成了有狀態的機器,為以後實現容災造成了羈絆。

 

Session管理-Session 複製

 

20170504103118859.jpg

 

就像我們在所有的飯店裏都存一份自己的碗筷。這樣隨意去哪一家飯店吃飯都OK,不適合做大規模集群,適合機器不多的情況。

 

解決了我們session共享的問題,但是它有什麼缺點呢?

 

  1. 應用服務器間帶寬問題,因為需要不斷同步session數據。

  2. 大量用戶在線時,服務器占用內存過多。

 

Session管理-基於Cookie

 

20170504103127709.jpg

 

打個比方,就是我們每次去飯店吃飯,都帶著自己的碗筷去。

 

解決了我們session共享的問題,但是它有什麼缺點呢?

 

  1. cookie 的長度限製。

  2. cookie存於瀏覽器,安全性是一個問題。

 

Session管理-Session 服務器

 

20170504103135378.jpg

 

打個比方,就是我們的碗筷都存在了一個龐大的櫥櫃裏,我們去任何一家飯店吃飯,都可以從櫥櫃中拿到屬於我們自己的碗筷。

 

解決了我們session共享的問題,這種方案需要思考哪些問題呢?

 

  1. 保證 session 服務器的可用性,session服務器單點如何解決?

  2. 我們在寫應用時需要做調整存儲session的業務邏輯。

 

打個比方,為了提高session server的可用性,我們可以繼續給session server做集群。

 

五、中間總結

 

所以網站架構在遇到某些指標瓶頸、演進的過程中,都有哪些解決方案?它們都有什麼優缺點?業務功能上如何取舍?如何做出選擇?這個過程才是最重要的。

 

在解決了橫向擴展應用服務器之後,我們繼續回到目前的架構圖:

 

20170504103144220.jpg

 

數據庫的讀及寫操作都還需要經過數據庫。當用戶量達到一定量,數據庫將會成為瓶頸。又該如何解決呢?

 

六、數據庫讀寫分離

 

20170504103153408.jpg

 

使用數據庫提供的熱備功能,將所有的讀操作引入slave 服務器,因為數據庫的讀寫分離了,所以我們的應用程序也得做出相應的變化。我們實現了一個數據訪問模塊(圖中的data access module),使上層寫代碼的人不知道讀寫分離的存在。這樣多數據源讀寫分離就對業務代碼沒有了侵入。同時這裏引出了代碼層次的演變。

 

思考的點

 

  1. 如何支持多數據源?

  2. 如何封裝對業務沒有侵入?

  3. 如何使用目前業務的ORM框架完成主從讀寫分離?是否需要更4. 換ORM模型?ORM模型之間各有什麼優缺點?

  4. 如何取舍?

 

數據庫讀寫分離會遇到如下問題:

 

  1. 在master和slave複製的時候,考慮延時問題、數據庫的支持、複製條件的支持。

  2. 當為了提高可用性,將數據庫分機房後,跨機房傳輸同步數據,這個更是問題。

  3. 應用對於數據源的路由問題。

 

七、使用反向代理和CDN加速網站響應

 

20170504103200957.jpg

 

使用 CDN 可以很好地解決不同的地區的訪問速度問題,反向代理則在服務器機房中緩存用戶資源。

 

訪問量越來越大,我們文件服務器也出現了瓶頸。

 

八、分布式文件係統

 

20170504103209310.jpg

思考的點

 

  1. 分布式文件係統如何不影響已部署在線上的業務訪問?不能讓某個圖片突然訪問不到呀。

  2. 是否需要業務部門清洗數據?

  3. 是否需要重新做域名解析?

 

這時數據庫又出現了瓶頸。

 

九、數據垂直拆分

 

20170504103217261.jpg

 

數據庫專庫專用,如圖Products、Users、Deal庫。解決寫數據時並發量大的問題。

 

思考的點

 

  1. 跨業務的事務如何解決?使用分布式事務、去掉事務或不追求強事務。

  2. 應用的配置項多了。

  3. 如何跨庫進行數據的join操作?

 

這個時候,某個業務的數據表的數據量或者更新量達到了單個數據庫的瓶頸。

 

十、數據水平拆分

 

20170504103226864.jpg

 

如圖,我們把User拆成了User1和User2,將同一個表的數據拆分到兩個數據庫中,解決了單數據庫的瓶頸。

 

思考的點

 

  1. 水平拆分的策略都有哪些?各有什麼優缺點?

  2. 水平拆分的時候如何清洗數據?

  3. SQL的路由問題,需要知道某個User在哪個數據庫上。

  4. 主鍵的策略會有不同。

  5. 假設係統中需要查詢2017年4月份已經下單過的用戶名的明細,而這些用戶分布在user1和user2上,我們後台運營係統在展示時如何分頁?

 

這個時候,公司對外部做了流量導入,我們應用中的搜索量飆升,繼續演進。

 

十一、拆分搜索引擎

 

20170504103234654.jpg

 

使用搜索引擎,解決數據查詢問題。部分場景可使用NoSQL提高性能,開發數據統一訪問模塊,解決上層應用開發的數據源問題。如圖data access module 可以訪問數據庫、搜索引擎、NoSQL。

 

總結

 

本文隻是一個舉例演示,各個服務的技術架構需要根據自己業務特點進行優化和演進,所以大家的過程也不完全相同。

 

最後的這個示例也不是完美的,例如負載均衡還是一個單點,也需要集群,我們這個架構也隻是冰山一角。因為在架構演進的過程中,還要考慮係統的安全性、數據分析、監控、反作弊等,同時往後繼續發展,也要考慮到SOA架構、服務化、消息隊列、任務調度、多機房等。

 

從以上對架構演進的講解,也可以看出來,所有大型項目的架構和代碼,都是一步一步根據實際的業務場景和發展情況發展演變而來,在不同的階段,會使用的不同的技術,不同的架構來解決實際的問題,所以說,高大上的項目技術架構和開發設計實現不是一蹴而就的。

 

正是所謂的萬丈高樓平地起。在架構演進的過程中,小到核心模塊代碼,大到核心架構,都會不斷演進的,這個過程值得我們去深入學習和思考。

 原文發布時間為:2017-05-14

本文來自雲棲社區合作夥伴DBAplus

最後更新:2017-05-17 14:01:58

  上一篇:go  Erlang入門(二)—並發編程
  下一篇:go  Erlang簡史(翻譯)