透過接觸有關海量資料處理和搜尋引擎的諸多技術,常常見識到不少精妙絕倫的架構圖。除了每每感嘆於每幅圖表面上的繪製的精細之外,更為架構圖背後所隱藏的設計思想所歎服。個人這兩天一直在蒐集各大型網站的架構設計圖,一為了一飽眼福,領略各類大型網站架構設計的精彩之外,二來也可供閒時反覆琢磨體會,何樂而不為呢? 特此,總結整理了諸如國外 wikipedia,Facebook,Yahoo!,YouTube,MySpace,Twitter,國內如優酷網等大型網站的技術架構(本文重點分析優酷網的技術架構),以饗讀者。
本文著重凸顯每一幅圖的精彩之處與其背後含義,而圖的說明性文字則從簡從略。 ok,好好享受此番架構盛宴吧。當然,若有任何建議或問題,歡迎不吝指正。謝謝。
1 、 WikiPedia 技術架構
WikiPedia 技術架構圖 Copy @Mark Bergsma
來自 wikipedia 的資料:峰值每秒鐘 3 萬個 HTTP 請求 每秒鐘 3Gbit 流量, 近乎 375MB 350 臺 PC 伺服器。
GeoDNSA :40-line patch for BIND to add geographical filters support to the existent views in BIND”, 把多使用者帶到近的伺服器。 GeoDNS 在 WikiPedia 架構中擔當重任當然是由 WikiPedia 的內容性質決定的– 面向各個國家,各個地域。
負載均衡:LVS,請看下圖:
。
2 、 Facebook 架構
Facebook 搜尋功能的架構示意圖
細心的讀者一定能發現,上副架構圖之前出現在此文之中:從幾幅架構圖中偷得半點海里資料處理經驗。本文與前文大的不同是,前文只有幾幅,此文系列將有上百幅架構圖,任您盡情觀賞。
3 、 Yahoo! Mail 架構
Yahoo! Mail 架構
Yahoo! Mail 架構部署了 Oracle RAC,用來儲存 Mail 服務相關的 Meta 資料。
4 、 twitter 技術架構
twitter 的整體架構設計圖
twitter 平臺大致由 twitter.com 、手機以及第三方應用構成,如下圖所示(其中流量主要以手機和第三方為主要來源):
快取在大型 web 專案中起到了舉足輕重的作用,畢竟資料越靠近 CPU 存取速度越快。下圖是 twitter 的快取架構圖:
關於快取系統,還可以看看下幅圖:
5 、 Google WordPress APP Engine 技術架構
GAE 的架構圖
簡單而言,上述 GAE 的架構分為如圖所示的三個部分:前端,Datastore 和服務群。
前端包括 4 個模組:Front End,Static Files,WordPress APP Server,WordPress APP Master 。
Datastore 是基於 BigTable 技術的分散式資料庫,雖然其也可以被理解成為一個服務,但是由於其是整個 WordPress APP Engine 儲存持久化資料的地方,所以其是 WordPress APP Engine 中一個非常核心的模組。其具體細節將在下篇和大家討論。
整個服務群包括很多服務供 WordPress APP Server 呼叫,比如 Memcache,圖形,多使用者,URL 抓取和任務佇列等。
6 、 Amazon 技術架構
Amazon 的 Dynamo Key-Value 儲存架構圖
可能有讀者並不熟悉 Amazon,它現在已經是全球商品品種多的網上零售商和全球第 2 大網際網路公司。而之前它僅僅是一個小小的網上書店。 ok,下面,咱們來見識下它的架構。
Dynamo 是亞馬遜的 key-value 模式的儲存平臺,可用性和擴充套件性都很好,效能也不錯:讀寫訪問中 99.9% 的響應時間都在 300ms 內。按分散式系統常用的雜湊演演算法切分資料,分放在不同的 node 上。 Read 操作時,也是根據 key 的雜湊值尋找對應的 node 。 Dynamo 使用了 Consistent Hashing 演演算法,node 對應的不再是一個確定的 hash 值,而是一個 hash 值範圍,key 的 hash 值落在這個範圍內,則順時針沿 ring 找,碰到的個 node 即為所需。
Dynamo 對 Consistent Hashing 演演算法的改進在於:它放在環上作為一個 node 的是一組機器(而不是 memcached 把一臺機器作為 node),這一組機器是透過同步機制保證資料一致的。
下圖是分散式儲存系統的示意圖,讀者可觀摩之:
Amazon 的雲架構圖如下:
Amazon 的雲架構圖
7 、優酷網的技術架構
從一開始,優酷網就自建了一套 CMS 來解決前端的頁面顯示,各個模組之間分離得比較恰當,前端可擴充套件性很好,UI 的分離,讓開發與維護變得十分簡單和靈活,下圖是優酷前端的模組呼叫關係:
這樣,就根據 module 、 method 及 params 來確定呼叫相對獨立的模組,顯得非常簡潔。下圖是優酷的前端區域性架構圖:
優酷的資料庫架構也是經歷了許多波折,從一開始的單臺 MySQL 伺服器(Just Running)到簡單的 MySQL 主從複製、 SSD 最佳化、垂直分庫、水平 sharding 分庫。
簡單的 MySQL 主從複製。
MySQL 的主從複製解決了資料庫的讀寫分離,並很好的提升了讀的效能,其原來圖如下:
其主從複製的過程如下圖所示:
但是,主從複製也帶來其他一系列效能瓶頸問題:
寫入無法擴充套件
寫入無法快取
複製延時
鎖表率上升
表變大,快取率下降
那問題產生總得解決的,這就產生下面的最佳化方案。
MySQL 垂直分割槽
如果把業務切割得足夠獨立,那把不同業務的資料放到不同的資料庫伺服器將是一個不錯的方案,而且萬一其中一個業務崩潰了也不會影響其他業務的正常進行,並且也起到了負載分流的作用,大大提升了資料庫的吞吐能力。經過垂直分割槽後的資料庫架構圖如下:
然而,儘管業務之間已經足夠獨立了,但是有些業務之間或多或少總會有點聯絡,如多使用者,基本上都會和每個業務相關聯,況且這種分割槽方式,也不能解決單張表資料量暴漲的問題,因此為何不試試水平 sharding 呢?
MySQL 水平分片(Sharding)
這是一個非常好的思路,將多使用者按一定規則(按 id 雜湊)分組,並把該組多使用者的資料儲存到一個資料庫分片中,即一個 sharding,這樣隨著多使用者數量的增加,只要簡單地配置一臺伺服器即可,原理圖如下:
如何來確定某個多使用者所在的 shard 呢,可以建一張多使用者和 shard 對應的資料表,每次請求先從這張表找多使用者的 shard id,再從對應 shard 中查詢相關資料,如下圖所示: 但是,優酷是如何解決跨 shard 的查詢呢,這個是個難點,據介紹優酷是儘量不跨 shard 查詢,實在不行透過多維分片索引、分散式搜尋引擎,下策是分散式資料庫查詢(這個非常麻煩而且耗效能)。
快取策略
貌似大的系統都對 “快取” 情有獨鍾,從 http 快取到 memcached 記憶體資料快取,但優酷表示沒有用記憶體快取,理由如下:
避免記憶體複製,避免記憶體鎖
如接到老大哥通知要把某個視訊撤下來,如果在快取裡是比較麻煩的
而且 Squid 的 write() 多使用者程式空間有消耗,Lighttpd 1.5 的 AIO(非同步 I/O) 讀取檔案到多使用者記憶體導致效率也比較低下。
但為何我們訪問優酷會如此流暢,與土豆相比優酷的視訊載入速度略勝一籌?這個要歸功於優酷建立的比較完善的內容分發網路(CDN),它透過多種方式保證分佈在全國各地的多使用者進行就近訪問——多使用者點選視訊請求後,優酷網將根據多使用者所處地區位置,將離多使用者近、服務狀況知名的視訊伺服器地址傳送給多使用者,從而保證多使用者可以得到快速的視訊體驗。這就是 CDN 帶來的優勢,就近訪問。