在上一篇《知名網站的技術發展歷程》中,介紹了一些知名網站在發展的過程中技術的演變,在這篇文章中則會根據這些網站的發展經驗,來總結通常網站是如何來應對可伸縮性、可用性、高性能以及低成本這四方面的挑戰的。
在上一篇文章中,介紹了一些Alexa排名較前的網站的技術發展歷程,在這篇文章中,將結合提及到的網站的技術發展歷程,來總結下網站在可伸縮性、可用性、高性能以及低成本四點上通常采用的技術。
對于一個網站而言,最重要的是要支撐住不斷增長的訪問量和數據量,如果能做到簡單的增加機器即可支撐,那自然是最好的,但這就要求技術上必須付出一定的努力,這也是網站都追求的可伸縮性(Scalability),而在做到可伸縮性后,不斷增加的機器也帶來了成本的上升,因此發展到了一定規模后,成本也會成為關注的重點。
除了可伸縮性外,可用性對于各網站而言也非常重要,一個經常不能使用的網站必被用戶拋棄,這也是為什么各網站都很強調全年的可用性。
除了上面這三點外,還有另外一點影響也很明顯,就是性能,美國的一個對網站訪問速度的調查數據:1/4的用戶因為一個網站載入的時間超過4秒而放棄這個網站,50%的手機用戶會放棄一個超過10秒還沒載入完成的網站,其中的3/5用戶將不再光顧這個網站,而Google對其數據分析后,發現搜索結果只要慢1/4秒,一天的搜索量就要減少800萬。
可伸縮
可伸縮分為垂直伸縮和水平伸縮,垂直伸縮為通過升級機器的硬件來解決問題,水平伸縮為通過增加機器來解決問題,不同網站在可伸縮上采用了不同的策略,例如Google完全依賴水平伸縮來解決問題,而其他網站多數是先依賴垂直伸縮來解決數據存儲的問題。
垂直伸縮要求的是軟件上要能在硬件升級的情況下,發揮出硬件的能力,例如可配置的并行數、內存等,硬件的發展速度非常迅猛,網站的機器的配置自然也是每年都在升級,因此其實我們的軟件時刻都在被檢驗是否能垂直伸縮。
水平伸縮主要要解決的是如何做到僅通過增加機器就解決問題,主要又分成了應用層和存儲層兩個層次來解決。
在應用層要做到水平伸縮,通常采用的策略是Share Nothing/Stateless,狀態信息放入客戶端或存儲層(例如用戶的Session信息放入Cookie,或放入服務器端的緩存系統),應用系統做到了無狀態,那么在訪問量上漲后只需要增加機器即可,在應用系統由單臺增加到多臺組成Cluster時,這時就會有負載均衡的引入,可能是硬件的也可能是軟件的。
在應用層的結構演變上,我們會發現,隨著網站的不斷發展,以上提到的各家網站在應用層上最后形成的結構幾乎都完全一樣,均為前端Web系統Cluster + Services Cluster,前端Web系統和Services到了一定的階段后通常又會按照一定的規則來進行拆分,如按業務領域等,可見SOA其實在大網站中是落地了的,而不像企業領域中宣傳的那么虛。
在存儲層要做到水平伸縮,難度就比應用層大多了,從前面各家網站的發展歷程也可看出,很多時候都在解決存儲層的問題,而且可以看出,很多網站由于業務發展的壓力較大,一開始都會選擇采用垂直伸縮的方式來解決存儲層的問題。
存儲層主要是Cache、文件和數據三種類型。
Cache可以看到基本上各家網站都采用了Memcache來保證伸縮性,在規模大了,也會碰到一些問題,具體可以看看facebook所做的改造,現在也有些網站開始采用redis了,但redis本身不具備可伸縮性,需要自行進行改造。
文件的存儲可以看到各家網站都采用了分布式文件系統來保證伸縮性,思路多數都源于GFS,但由于存儲的文件的大小不同、對響應時間和吞吐量的要求不同,各家網站可能都各自實現。
數據的存儲上可以看到各家網站基本都采用了分庫分表的策略,分庫分表后由于很多關系型數據庫的特性(例如自增ID、join、事務等)都難以再使用了,對應用的設計會帶來一些挑戰,不過最大難點還是在于需要根據業務來考慮如何分是合適的,在最近幾年也有一些網站開始采用NoSQL來更好的做到數據存儲的可伸縮性。
存儲層為了做到可伸縮性,通常采用的方案是單點寫(是指在某個粒度的單點,例如對HBase而言,是單行數據一定是在同一臺機器上進行寫操作),但讀可能是多點,讀多點的話主要要考慮不一致的問題,無論讀是單點還是多點,數據都會在軟件層面做到寫多份,策略主要有同步寫多份、投票寫多份、異步復制最終一致等(例如HDFS、Cassandra、Zookeeper),采用自動分裂的方法來實現數據量增長時的自動伸縮,采用一致性hash或根據某種規則的自動balance策略等來實現機器增減時的相應處理,同時也需要有感知機器增減的方法(例如采用zookeeper)。
從上面可以看到存儲層上要做到可伸縮,技術上的難點很多,這也是為什么大規模的網站都不在數據庫上做復雜的運算,而只是把其當做一種存儲來使用,例如存儲過程這種就更是基本不會出現了,以降低數據庫的壓力。
除了應用層和存儲層需要做到可伸縮外,硬件層面的可伸縮在設計系統時也是需要考慮的,例如硬件負載設備只能支撐到一定的流量,同樣也需要考慮如何讓其能夠可伸縮。
除了盡可能做到系統可伸縮外,減少對系統的壓力也是緩解系統的可伸縮面臨挑戰的方法,例如批量提交、最終一致、youtube提到的“欺騙”、適當的正確性等策略。
可伸縮性是網站從小到大要經歷的第一關挑戰,而且隨著網站的不斷發展,還要不斷的做技術改造才能保證網站在每個不同的階段(例如同機房階段、同城多機房階段、異地多機房階段)都具備優秀的可伸縮性,不過幸運的是不同階段的可伸縮性方案都已經比較成熟。
可用性
可伸縮性保證了網站在不斷增長的訪問量和數據量的情況下生存下來,這也一定程度保證了網站的可用性,但除了這點外,要保障系統的可用性,還得付出很多的努力。
在設計高可用性的系統時,避免單點是其中最重要的一點,通常采用主備和集群的方法來避免單點,例如負載均衡設備、MySQL等通常采用主備的方式,在BigTable里采取了一種比較特殊的方法來避免Tablet Server的單點:通過Chubby來感知Tablet Server的健康狀況,如發現Tablet Server掛掉了,則由Master將此Tablet Server負責的Tablet遷移到其他的Tablet Servers上。
原文轉自:http://bluedavy.me/?p=396