1. 程式人生 > >淘寶網用什麼樣的伺服器

淘寶網用什麼樣的伺服器

時間過得很快,來淘寶已經兩個月了,在這兩個月的時間裡,自己也感受頗深。下面就結合淘寶目前的一些底層技術框架以及自己的一些感觸來說說如何構建一個可伸縮,高效能,高可用性的分散式網際網路應用。

一 應用無狀態(淘寶session框架)

俗話說,一個系統的伸縮性的好壞取決於應用的狀態如何管理。為什麼這麼說呢?咱們試想一下,假如我們在session中儲存了大量與客戶端的狀態資訊的話,那麼當儲存狀態資訊的server宕機的時候,我們怎麼辦?通常來說,我們都是通過叢集來解決這個問題,而通常所說的叢集,不僅有負載均衡,更重要的是要有失效恢復failover,比如tomcat採用的叢集節點廣播複製,jboss採 用的配對複製等session狀態複製策略,但是叢集中的狀態恢復也有其缺點,那就是嚴重影響了系統的伸縮性,系統不能通過增加更多的機器來達到良好的水平伸縮,因為叢集節點間session的通訊會隨著節點的增多而開銷增大,因此要想做到應用本身的伸縮性,我們需要保證應用的無狀態性,這樣叢集中的各個節點來說都是相同的,從而是的系統更好的水平伸縮。

OK,上面說了無狀態的重要性,那麼具體如何實現無狀態呢?此時一個session框架就會發揮作用了。幸運的是淘寶已經具有了此類框架。淘寶的session框架採用的是client cookie實現,主要將狀態儲存到了cookie裡面,這樣就使得應用節點本身不需要儲存任何狀態資訊,這樣在系統使用者變多的時候,就可以通過增加更多的應用節點來達到水平擴充套件的目的.但是採用客戶端cookie的方式來儲存狀態也會遇到限制,比如每個cookie一般不能超過4K的大小,同時很多瀏覽器都限制一個站點最多儲存20個cookie.淘寶cookie框 架採用的是“多值cookie”, 就是一個組合鍵對應多個cookie的 值,這樣不僅可以防止cookie數量超過20, 同時還節省了cookie儲存有效資訊的空間,因為預設每個cookie都會有大約50個位元組的元資訊來描述cookie。

除了淘寶目前的session框架的實現方式以外,其實集中式session管理來完成,說具體點就是多個無狀態的應用節點連線一個session 伺服器,session服 務器將session保 存到快取中,session伺服器後端再配有底層永續性資料來源,比如資料庫,檔案系統等等。

二 有效使用快取(Tair)

做網際網路應用的兄弟應該都清楚,快取對於一個網際網路應用是多麼的重要,從瀏覽器快取,反向代理快取,頁面快取,區域性頁面快取,物件快取等等都是快取應用的場景。

一 般來說快取根據與應用程式的遠近程度不同可以分為:local cache 和 remote cache。一般系統中要麼採用local cache,要麼採用remote cache,兩者混合使用的話對於local cache和remote cache的資料一致性處理會變 大比較麻煩.

在大部分情況下,我 們所說到的快取都是讀快取,快取還有另外一個型別:寫快取. 對於一些讀寫比不高,同時對資料安全性需求不高的資料,我們可以將其快取起來從而減少對底層資料庫的訪問,比如 統計商品的訪問次數,統計API的 呼叫量等等,可 以採用先寫記憶體快取然後延遲持久化到資料庫,這樣可以大大減少對資料庫的寫壓力。

OK,我以店鋪線的系統為例,在使用者瀏覽店鋪的時候,比如店鋪介紹,店鋪交流區頁面,店鋪服務條款頁面,店鋪試衣間頁面,以及店鋪內搜尋介面這些介面更新不是非常頻繁,因此適合放到快取中,這樣可以大大減低DB的負載。另外寶貝詳情頁面相對也更新比較少,因此也適合放到快取中來減低DB負載。

三 應用拆分(HSF)

首先,在說明應用拆分之前,我們先來回顧一下一個系統從小變大的過程中遇到的一些問題,通過這些問題我們會發現拆分對於構建一個大型系統是如何的重要。

系統剛上線初期,使用者數並不多,所有的邏輯也許都是放在一個系統中的,所有邏輯跑到一個程序或者一個應用當中,這個時候因為比較使用者少,系統訪問量低,因此將全部的邏輯都放在一個應用未嘗不可。但是,兄弟們都清楚,好景不長,隨著系統使用者的不斷增加,系統的訪問壓力越來越多,同時隨著系統發展,為了滿足使用者的需求,原有的系統需要增加新的功能進來,系統變得越來越複雜的時候,我們會發現系統變得越來越難維護,難擴充套件,同時系統伸縮性和可用性也會受到影響。那麼這個時候我們如何解決這些問題呢?明智的辦法就是拆分(這也算是一種解耦),我們需要將原來的系統根據一定的標準,比如業務相關性等分為不同的子系統,不同的系統負責不同的功能,這樣切分以後,我們可以對單獨的子系統進行擴充套件和維護,從而提高系統的擴充套件性和可維護性,同時我們系統的水平伸縮性scale out大大的提升了,因為我們可以有針對性的對壓力大的子系統進行水平擴充套件而不會影響到其它的子系統,而不會像拆分以前,每次系統壓力變大的時候,我們都需要對整個大系統進行伸縮,而這樣的成本是比較大的,另外經過切分,子系統與子系統之間的耦合減低了,當某個子系統暫時不可用的時候,整體系統還是可用的,從而整體系統的可用性也大大增強了。

因此一個大型的網際網路應用,肯定是要經過拆分,因為只有拆分了,系統的擴充套件性,維護性,伸縮性,可用性才會變的更好。但是拆分也給系統帶來了問題,就是子系統之間如何通訊的問題,而具體的通訊方式有哪些呢?一般有同步通訊和非同步通訊,這裡我們首先來說下同步通訊,下面的主題“訊息系統”會說到非同步通訊。既然需要通訊,這個時候一個高效能的遠端呼叫框架就顯得非常總要啦,因此咱們淘寶也有了自己的HSF框 架。

上面所說的都是拆分的好處,但是拆分以後必然的也會帶來新的問題,除了剛才說的子系統通訊問題外,最值得關注的問題就是系統之間的依賴關係,因為系統多了,系統的依賴關係就會變得複雜,此時就需要更好的去關注拆分標準,比如能否將一些有依賴的系統進行垂直化,使得這些系統的功能儘量的垂直,這也是目前淘寶正在做的系統垂直化,同時一定要注意系統之間的迴圈依賴,如果出現迴圈依賴一定要小心,因為這可能導致系統連鎖啟動失敗。

OK,既然明白了拆分的重要性,我們看看隨著淘寶的發展,淘寶本身是如何拆分系統的。

首先我們來看以下這個圖:(作者圖片已無法開啟,請見諒)

從上面的圖可以看出淘寶系統的一個演變過程,在這個演變的過程中,我們所說的拆分就出現V2.2和V3.0之 間。在V2.2版本中,淘寶幾乎所有的邏輯都放在(Denali)系統中,這樣導致的問題就是系統擴充套件和修改非常麻煩,並且更加致命的是隨著淘寶業務量的增加,如果按照V2.2的架構已經沒有辦法支撐以後淘寶的快速發展,因此大家決定對整個系統進行拆分,最終V3.0版本的淘寶系統架構圖如下:(作者圖片已無法開啟,請見諒)

從上圖可以看出V3.0版本的系統對整個系統進行了水平和垂直兩個方向的拆分,水平方向上,按照功能分為交易,評價,使用者,商品等系統,同樣垂直方向上,劃分為業務系統,核心業務系統以及以及基礎服務,這樣以來,各個系統都可以獨立維護和獨立的進行水平伸縮,比如交易系統可以在不影響其它系統的情況下獨立的進行水平伸縮以及功能擴充套件。

從上面可以看出,一個大型系統要想變得可維護,可擴充套件,可伸縮,我們必須的對它進行拆分,拆分必然也帶來系統之間如何通訊以及系統之間依賴管理等問題,關於通訊方面,淘寶目前獨立開發了自己的高效能服務框架HSF, 此框架主要解決了淘寶目前所有子系統之間的同步和非同步通訊(目前HSF主要用於同步場合,FutureTask方式的呼叫場景還比較少)。至於系統間的依賴管理,目前淘寶還做的不夠好,這應該也是我們以後努力解決的問題。

四 資料庫拆分(TDDL)

在前面“應用拆分”主題中,我們提到了一個大型網際網路應用需要進行良好的拆分,而那裡我們僅僅說了”應用級別”的拆分,其實我們的網際網路應用除了應用級別的拆分以外,還有另外一個很重要的層面就是儲存如何拆分的。因此這個主題主要涉及到如何對儲存系統,通常就是所說的RDBMS進行拆分。

好了,確定了這個小節的主題之後,我們回顧一下,一個網際網路應用從小變大的過程中遇到的一些問題,通過遇到的問題來引出我們拆分RDBMS的重要性。

系統剛開始的時候,因為系統剛上線,使用者不多,那個時候,所有的資料都放在了同一個資料庫中,這個時候因為使用者少壓力小,一個數據庫完全可以應付的了,但是隨著運營那些哥們辛苦的吶喊和拼命的推廣以後,突然有一天發現,oh,god,使用者數量突然變多了起來,隨之而來的就是資料庫這哥們受不了,它終於在某一天大家都和愜意的時候掛掉啦。此時,咱們搞技術的哥們,就去看看究竟是啥原因,我們查了查以後,發現原來是資料庫讀取壓力太大了,此時咱們都清楚是到了讀寫分離的時候,這個時候我們會配置一個server為master節點,然後配幾個salve節點,這樣以來通過讀寫分離,使得讀取資料的壓力分攤到了不同的salve節點上面,系統終於又恢復了正常,開始正常運行了。但是好景還是不長,有一天我們發現master這哥們撐不住了,它負載老高了,汗流浹背,隨時都有翹掉的風險,這個時候就需要咱們垂直分割槽啦(也就是所謂的分庫),比如將商品資訊,使用者資訊,交易資訊分別儲存到不同的資料庫中,同時還可以針對商品資訊的庫採用master,salve模式,OK,通過分庫以後,各個按照功能拆分的資料庫寫壓力被分擔到了不同的server上面,這樣資料庫的壓力終於有恢復到正常狀態。但是是不是這樣,我們就可以高枕無憂了呢?NO,這個NO,不是我說的,是前輩們通過經驗總結出來的,隨著使用者量的不斷增加,你會發現系統中的某些表會變的異常龐大,比如好友關係表,店鋪的引數配置表等,這個時候無論是寫入還是讀取這些表的資料,對資料庫來說都是一個很耗費精力的事情,因此此時就需要我們進行“水平分割槽”了(這就是俗話說的分表,或者說sharding).

OK,上 面說了一大堆,無非就是告訴大家一個事實“資料庫是系統中最不容易scale out的一層”,一個大型的網際網路應用必然會經過一個從單一DB server,到Master/salve,再到垂直分割槽(分庫),然後再到水平分割槽(分表,sharding)的過程,而在這個過程中,Master/salve 以 及垂直分割槽相對比較容易,對應用的影響也不是很大,但是分表會引起一些棘手的問題,比如不能跨越多個分割槽join查詢資料,如何平衡各個shards的負載等等,這個時候就需要一個通用的DAL框架來遮蔽底層資料儲存對應用邏輯的影響,使得底層資料的訪問對應用透明化。

拿淘寶目前的情況來說,淘寶目前也正在從昂貴的高階儲存(小型機+ORACLE)切換到MYSQL,切 換到MYSQL以後,勢必會遇到垂直分割槽(分庫)以及水平分割槽(Sharding)的問題,因此目前淘寶根據自己的業務特點也開發了自己的TDDL框架,此框架主要解決了分庫分表對應用的透明化以及異構資料庫之間的資料複製

五 非同步通訊(Notify)

在”遠 程呼叫框架”的 介紹中,我 們說了一個大型的系統為了擴充套件性和伸縮性方面的需求,肯定是要進行拆分,但是 拆分了以後,子系統之間如何通訊就成了我們首要的問題,在”遠端呼叫框架”小節 中,我們說了同步通訊在一個大型分散式系統中的應用,那麼這一小節我們就來說說非同步通訊.好了,既 然說到了非同步通訊,那 麼”消 息中介軟體”就要登場了,採 用非同步通訊這其實也是關係到系統的伸縮性,以及最大化的對各個子系統進行解耦.

說到非同步通訊,我們需要關注的一點是這裡的非同步一定是根據業務特點來的,一定是針對業務的非同步,通常適合非同步的場合是一些鬆耦合的通訊場合,而對於本身業務上關聯度比較大的業務系統之間,我們還是要採用同步通訊比較靠譜。

OK,那 麼下一步我們說說非同步能給系統帶來什麼樣子的好處。首先我們想想,假如系統有A和B兩個 子系統構成,假如A和B是同步通訊的話,那麼要想使得系統整體伸縮性提高必須同時對A和B進行 伸縮,這就影響了對整個系統進行scale out.其次,同步呼叫還會影響到可用性,從數學推理的角度來說,A同 步呼叫B, 如果A可 用,那麼B可 用,逆否命題就是如果B不可用,那麼A也不可用,這將大大影響到系統可用性,再次,系統之間非同步通訊以後可以大大提高系統的響應時間,使得每個請求的響應時間變短,從而提高使用者體驗,因此非同步在提高了系統的伸縮性以及可用性的同時,也大大的增強了請求的響應時間(當然了,請求的總體處理時間也許不會變少)。

下面我們就以淘寶的業務來看看非同步在淘寶的具體應用。交易系統會與很多其它的業務系統互動,如果在一次交易過程中採用同步呼叫的話,這就要求要向交易成功,必須依賴的所有系統都可用,而如果採用非同步通訊以後,交易系統藉助於訊息中介軟體Notify和其它的系統進行了解耦,這樣以來當其它的系統不可用的時候,也不會影響到某此交易,從而提高了系統的可用性。

最後,關於非同步方面的討論,我可以 推薦大家一些資源:

1 . J2EE meets web2.0

2. Ebay架構特點(HPTS 2009)

六 非結構化資料儲存 ( TFS,NOSQL)

在一個大型的網際網路應用當中,我們會發現並不是所有的資料都是結構化的,比如一些配置檔案,一個使用者對應的動態,以及一次交易的快照等資訊,這些資訊一般不適合儲存到RDBMS中,它們更符合一種Key-value的結構,另外還有一類資料,資料量非常的大,但是實時性要求不高,此時這些資料也需要通過另外的一種儲存方式進行儲存,另外一些靜態檔案,比如各個商品的圖片,商品描述等資訊,這些資訊因為比較大,放入RDBMS會引起讀取效能問題,從而影響到其它的資料讀取效能,因此這些資訊也需要和其它資訊分開儲存,而一般的網際網路應用系統都會選擇把這些資訊儲存到分散式檔案系統中,因此淘寶目前也開發了自己的分散式檔案系統TFS,TFS目前限制了檔案大小為2M, 適合於一些小於2M數 據的存放。

隨 著網際網路的發展,業界從08年下半年開始逐漸流行了一個概念就是NOSQL。我們都知道根據CAP理論,一致性,可用性和分割槽容錯性3者不能同時滿足,最多隻能同時滿足兩個,我們傳統的關係資料採用了ACID的事務策略,而ACID的事務策略更加講究的是一種高一致性而降低了可用性的需求,但是網際網路應用往往對可用性的要求要略高於一致性的需求,這個時候我們就需要避免採用資料的ACID事務策略,轉而採用BASE事 務策略,BASE事務策略是基本可用性,事務軟狀態以及最終一致性的縮寫,通過BASE事務策略,我們可以通過最終一致性來提升系統的可用性,這也是目前很多NOSQL產品所採用的策略,包括facebook 的cassandra,apache hbase,google bigtable等,這些產品非常適合一些非結構化的資料,比如key-value形式的資料儲存,並且這些產品有個很好的優點就是水平伸縮性。目前淘寶也在研究和使用一些成熟的NOSQL產品。

七 監控、預警系統

對於大型的系統 來說,唯一可靠的就是系統的各個部分是不可靠。

因為一個大型的分散式系統中勢必會涉及到各種各樣的裝置,比如網路交換機,普通PC機,各種型號的網絡卡,硬碟,記憶體等等,而這些東東都在數量非常多的時候,出現錯誤的概率也會變大,因此我們需要時時刻刻監控系統的狀態,而監控也有粒度的粗細之分,粒度粗一點的話,我們需要對整個應用系統進行監控,比如目前的系統網路流量是多少,記憶體利用率是多少,IO,CPU的負載是多少,服務的訪問壓力是多少,服務的響應時間是多少等這一系列的監控,而細粒度一點的話,我們就需對比如應用中的某個功能,某個URL的訪問量是多,每個頁面的PV是多少,頁面每天佔用的頻寬是多少,頁面渲染時間是多少,靜態資源比如圖片每天佔用的頻寬是多少等等進行進一步細粒度的監控。因此一個監控系統就變得必不可少了。

前面說了一個監控系統的重要性,有了監控系統以後,更重要的是要和預警系統結合起來,比如當某個頁面訪問量增多的時候,系統能自動預警,某臺Server的CPU和記憶體佔用率突然變大的時候,系統也能自動預警,當併發請求丟失嚴重的時候,系統也能自動預警等等,這樣以來通過監控系統和預警系統的結合可以使得我們能快速響應系統出現的問題,提高系統的穩定性和可用性。

八 配置統一管理

一個大型的分散式應用,一般都是有很多節點構成的,如果每次一個新的節點加入都要更改其它節點的配置,或者每次刪除一個節點也要更改配置的話,這樣不僅不利於系統的維護和管理,同時也更加容易引入錯誤。另外很多時候叢集中的很多系統的配置都是一樣的,如果不進行統一的配置管理,就需要再所有的系統上維護一份配置,這樣會造成配置的管理維護很麻煩,而通過一個統一的配置管理可以使得這些問題得到很好的解決,當有新的節點加入或者刪除的時候,配置管理系統可以通知各個節點更新配置,從而達到所有節點的配置一致性,這樣既方便也不會出錯。