偏愛MySQL,Nifty使用4個Web Server支撐5400萬個用戶網站

摘要:自基於HTML5的WYSIWYG網頁製作平臺推出後,用戶在Nifty上建立的網站已超過5400萬個,平均每天需支撐7億的HTTP請求,然而如果聚焦某個具體的網站,其PV甚至不超過100,那麼Nifty又使用了什麼策略解決這些長尾問題?

【編者按】Nifty運營網站已經有很長一段時間,而在基於HTML5的WYSIWYG網頁製作平臺推出後,用戶在該公司建立的網站已超過5400萬個,同時其中大部分網站的日PV都不到100。鑑於每個網頁的PV都很低,因此傳統的緩存策略並不適用。然而即使是這樣,該公司也只使用了4個Web Server就完成了這些工作。近日,Wix首席後端工程師Aviran Mordo在“ Wix Architecture at Scale”的演講中分享了他們的策略,下面我們一起看High Scalability創始人Todd Hoff的總結:

以下爲譯文

Wix圍繞擴展性上的努力可以用“定製化”三個字來總結——在仔細地審視了系統之後,以高可用和高性能爲目標對系統進行了改善。

Wix使用了多數據中心和雲服務,這在通常情況下非常少見,他們將數據同時複製到Google Compute Engine和AWS。對於故障轉移,他們有專門的應對策略。

從始至終,Wix都沒有使用事務。取而代之,所有數據都是不可變的,他們爲用例使用了一個非常簡單的最終一致性策略。Wix並不是緩存策略愛好者,簡而言之他們並沒有打造一個非常高端的緩存層。取而代之,他們將大部分的精力放在了路徑渲染優化上,讓每個頁面的顯示時間不超過100毫秒。

Wix開始於一個非常小的系統,使用了單片架構;而在業務發展過程中,他們很自然地過渡到一個面向服務的架構。在整個架構中,他們使用了一個非常成熟的服務識別策略,從而可以很輕易的將所有精力都集中到一個事件上來。

系統統計

  • 5400個網站,每個月都會新增100萬個
  • 800+TB的靜態數據,每天1.5TB的新文件
  • 3個數據中心+兩個雲服務(谷歌和亞馬遜)
  • 300個服務器
  • 每天7億個HTTP請求
  • 總計600員工,200人的研發團隊
  • 系統內服務數量達50個
  • 4個公共Web Server來支撐4500萬個網站

系統組件

  • MySQL
  • Google和Amazon雲服務
  • CDN(內容分發網絡)
  • Chef

系統衍變

1. 系統始於簡單的單片架構,開始時只有一個應用服務器,對於任何人來說,這都是最簡單的初始策略,非常靈活且易於更新。

  • Tomcat、Hibernate、定製網絡框架。
  • 使用有狀態的登錄。
  • 無視任何性能和擴展性相關。

2. 兩年後。

  • 仍然使用單片服務器支撐所有事情。
  • 擁有了一定規模的開發團隊,且需要支撐一定規模的用戶。
  • 依賴性產生的問題。某點的改變通常會造成整個系統的變更,無關領域的故障通常會造成整個系統大範圍崩潰。

3. 系統拆分的時候到了。

  • 到面向服務的架構轉變,但是這並不是件容易的事情。比如,你如何將某個功能分離到兩個服務中?
  • 聚焦用戶在系統中的行爲,並將之主要歸結爲3類:修改網站、查看Wix建立的網站以及媒體服務。
  • 網站更新包括服務器數據的數據有效性、安全和驗證、數據一致性以及大量的數據修改操作。
  • 一旦某個網站建立完成,用戶就會進行查看。因此,對於整個系統來說,訪客的數量十倍於修改者。因此關注點會轉換爲:

  • 高可用性。因爲用戶業務行爲,HA成爲系統最大的特性。
  • 高性能。
  • 高流量值。
  • 長尾問題。平臺上已經有了大量的網站,但是它們通常都非常小。單獨看某個網站,每天可能只有10或100個PV。鑑於這種特性,緩存對於系統擴展來說並不會起到太大的作用。因此,緩存變得非常低效。

  • 媒體支撐是第二大服務,包括HTML、javascript、css及images。他們需要一個途徑來支撐800TB數據上的大量請求,其中緩存靜態內容成爲制勝的關鍵。
  • 新系統看起來像一個網絡層,網站被切分爲3個部分服務:修改部分(任何對數據產生修改的操作),媒體部分(支撐靜態內容,只讀),公共部分(一個文件被訪問的首部分,只讀)。

服務打造的指導方針

  • 每個服務都有自己獨立的數據庫,每個數據庫只能一個被一個服務寫入。
  • 數據庫只能被服務的API訪問,這樣可以將關注點分離,並將數據模型對其他服務透明。
  • 鑑於性能原因,其他服務只被賦予數據庫的只讀權限,一個數據庫只能被一個服務寫入。
  • 服務都是無狀態的,這讓水平擴展非常便捷,業務的增長只需要添加更多服務器就可以支撐。
  • 不使用事務。除下billing/financial 事務以外,所有其他服務都不使用事務,這裏的理念是避免數據庫事務所帶來的開銷,從而提升性能。鑑於不使用事務,開發者必須考慮設計合適的數據模型來完成事務邏輯特性,從而避免不一致狀態。
  • 在新服務設計時,緩存並不是所需要考慮的因素。首先,儘可能的考慮服務性能,然後快速的部署到生產環境,查看服務的運行情況。只有在代碼無法優化的情況下,才使用緩存來解決性能問題。

更新服務

  • 更新服務必須處理大量的文件。
  • 數據被使用不可變的JSON pages在MySQL中存儲,每天大約250萬個。
  • MySQL是個非常棒的鍵值存儲。鍵的設定基於文件的哈希函數,因此鍵是不可變的,通過主鍵來訪問MySQL可以獲得非常理想的性能。
  • 可接受的擴展性。在擴展性方面,Wix又做了什麼樣的權衡?Wix之所以不使用NoSQL的原因是NoSQL往往會犧牲一致性,而通常開發者並不具備處理這種情況的能力,所以堅持MySQL也並非不可。
  • 動態數據庫。爲了給那些經常訪問的網站讓路,所有網站的冷數據(通常是建立時間超過3個月以上的數據)都會被轉移到其他的數據庫,這些數據庫的性能往往會非常低,但是容量很高。
  • 給用戶增長留有容量空間。大型檔案數據庫是非常緩慢的,但是鑑於數據使用的頻率這不會出現任何問題。但是一旦這個數據被訪問,在下次訪問之前這個數據就會被轉移到活躍數據庫。

打造更新服務的高可用性

  • 大數據體積達到一定程度時,任何事情的高可用都是難以保證的。因此,着眼關鍵路徑,在網站領域無疑就是網站的內容。如果網站的一個裝飾部分問題,它對網站的可用性不會造成任何致命影響。因此對一個網站來說,關鍵路徑纔是唯一關注點。
  • 防止數據庫崩潰。如果你想儘可能快的完成故障轉移,務必做好數據庫的備份,並在故障恢復時快速切換到從數據庫。
  • 數據完整性保護。這裏並不一定是惡意破壞,一個bug可能就會對數據存儲產生影響。所有數據都是不可變的,爲任何數據保存校訂版本。最壞的情況下,即使數據被破壞到無法修復,我們也可以將之恢復到修訂版本。
  • 阻止不可用情況發生。區別於桌面應用程序,網站必須可以被隨時隨地地訪問。因此,在不同地理位置的數據中心,不同雲環境中對數據進行備份非常重要,這將賦予系統足夠的彈性。

  • 在一個網站上點擊“保存”按鈕,修改會話會給修改服務器發送一個JSON文件。
  • 服務器會給活躍MySQL服務器發送頁面,同時它會在另一個數據中心進行備份。
  • 當數據在本地修改後,一個異步的進程會將修改上傳到一個靜態網格,也就是所謂的媒體部分。
  • 當數據被傳輸到靜態網格後,一個通知會發送給保存在Google Compute Engine上的存檔服務。存檔服務會連接到這個靜態網格,下載這個修改頁面,並將之保存在谷歌雲服務中。
  • 然後,一個通知會發送到修改器,告知頁面已經存儲到GCE。
  • 同時,系統會根據GCE的數據在Amazon中保存另一個副本。
  • 當最後一個通知收到後,這意味着這個數據已經保存了3個副本:一個數據庫,一個靜態網格以及一個GCE。
  • 對於新版本來說是3個副本,而對於舊版本來說則會存在兩個副本。
  • 這個過程具備自我修復的特性。如果這裏存在一個錯誤,當用戶下一次更新其網站內容時,所有未完成的修改會被重新上傳。
  • 停用文件會做垃圾收集處理。

使用無數據庫事務方式給數據建模

  • 對於服務擁有者來說,他們從來都不期望發生這樣的情況:用戶同時對兩個頁面進行修改,結果只有一個頁面被存儲到了數據庫中,這就造成了不一致狀態。
  • 取得所有JSON文件,隨後按照順序將他們保存到數據庫。當所有數據被保存後,一個命令會被髮布,它包含了上傳到這個靜態服務器上所有被保存頁面的ID清單(靜態服務器中文件名稱的哈希值)。

媒體部分

  • 存儲了大量文件。800TB的用戶媒體文件,平均每天300萬個文件,5億條元記錄。
  • 對圖像進行修改。它們會針對不同設備和屏幕對圖像進行修改。在這裏,可以根據需求插入水印,同時還可以對音頻格式進行轉換。
  • 建立一個一致性分佈式文件系統,使用多數據中心備份模式,並且實現跨數據中心的故障恢復。
  • 運行的痛苦。32個服務器,每9個月翻一倍。
  • 計劃遷移到雲中以獲得更好的擴展性。
  • 讓供應商鎖定見鬼。因爲都使用了API,只需要改變實現方式就可以在數週內跨雲服務供應商進行遷移。
  • 在Google Compute Engine中遭遇失敗。當他們從數據中心遷移到GCE時,很快就受到了谷歌雲服務的限制。而在谷歌做出了一些改變後,系統得以正常運行。
  • 數據是不可變的,因此非常有利於緩存。
  • 圖像請求會首先發送到CDN。如果所請求的圖像在CDN中並不存在,請求會被直接傳遞給他們奧斯丁的主數據中心。如果在主數據中心也沒有發現這個圖像,隨後尋找的地點就是谷歌雲服務。如果谷歌雲服務中仍然未發現所請求的圖像,那麼下一個尋找地點則是坦帕市的數據中心。

公用部分

  • 解析URL(在4500萬網站中),並將之分配給指定的渲染程序,然後轉換成HTML、sitemap XML或者robots TXT等。
  • 公用的SLA,峯值時響應時間低於100毫秒。網站必須是高可用的,同時也需要非常高的性能,但是緩存卻並不能發揮作用。
  • 當一個用戶修改某個頁面並進行發佈後,包括這個頁面元素的清單會被推送到公用環境,同時推送的還有路由表。
  • 最小化宕機情況。解析一次路由需要促發一個數據庫調用。將請求分配個渲染器需要1次RPC調用。獲得網站清單也需要一次數據庫調用。
  • 查詢表會在內存中進行緩存,每5分鐘修改一次。
  • 因爲需要傳送給編輯器,數據不可能保存爲同一種格式。數據使用非規範化格式進行存儲,通過主鍵進行優化,所有需求的內容都會在單一請求中返回。
  • 最小化業務邏輯。數據是非規範化的,並且進行預計算。大規模場景下,每秒內發生的每個操作都會乘以4500萬次,因此發生在公共服務器上的每個操作都需要被調整。
  • 頁面渲染

  • 由公共服務器返回的html是 bootstrap html類型的,它使用了一個JavaScript Shell,幷包含了所有網站清單和動態數據相關的JSON數據。
  • 渲染會被放在客戶端進行。當下,筆記本電腦和移動設備已經擁有了很強大的性能,它們完全可以從事這個工作。
  • 之所以選擇JSON,因爲解析和壓縮都非常方便。
  • 客戶端上的bug非常容易修補。修補客戶端bug只需要重新部署一個客戶端代碼,如果在服務器端進行渲染,html則會被緩存,因此修補一個bug需要重新渲染上千萬個網站。

公用部分的高可用性

  • 雖然目標是一直可用,但是總會發生一些意外情況
  • 通常情況下:請求由瀏覽器發出,隨之會被傳輸到一個數據中心,通過一個負載均衡器,它將會給發送到一個公共服務器,解析路由,傳送給渲染器,隨後返回到瀏覽器,並使用瀏覽器運行javascript。隨後,瀏覽器會對檔案服務發送請求,檔案服務會做與瀏覽器相同的操作,然後將數據儲存到緩存。
  • 數據中心丟失發生的情況:這時候,所有UPS都會掛掉,數據中心也會丟失。所有DNS都會被改變,請求會發送給次數據中心。
  • 公用部分丟失的情況:當負載均衡器配置只進行一半發生這個問題時,所有公共服務器都會丟失。或者當部署錯誤版本時,服務器則會拋出故障。Wix通過定製負載均衡器代碼來解決這個問題,在公共服務器丟失時,他們會將檔案服務器路由到高速緩存,即使系統在警報後已經進行故障恢復。
  • 在網絡連通性很爛的情況:請求由瀏覽器發出,隨之會被傳輸到一個數據中心,通過一個負載均衡器,並返回對應的html。現在JavaScript代碼必須取回所有的JSON數據和頁面。隨後進入內容分發網絡,發送到靜態網格,並獲得所有的文件進行網站渲染。在網絡很卡的情況下,文件返回可能無法進行。JavaScript則會做出選擇:如果主要位置無法獲得文件,代碼則會在檔案服務中獲取。

學到的知識

  • 識別業務的關鍵路勁和關注點,仔細瞭解產品運行的方式,開發使用場景,盡力讓你工作物有所值。
  • 使用多雲和多數據中心。爲了更好的可用性,在關鍵路徑上建立冗餘。
  • 對數據進行轉換,最小化進程外跳,一切只爲了性能。預計算並做一切可以做的事情來減少網絡抖動。
  • 利用好客戶端的CPU,爲可用性建立關鍵路徑上的冗餘。
  • 從小做起,先跑起來,然後尋找下一個決策。從始至終,Wix首要解決的都是如何才能讓服務可以良好運行的工作,然後有條不紊的轉移到面向服務的架構。
  • 長尾需要不同的途徑進行解決。取代緩存一切,Wix通過優化渲染途徑來提升服務,並將數據在活躍和檔案數據庫中同時進行備份。
  • 使用不可變的方式。不可變會對服務的架構產生深遠影響,覆蓋後端到客戶端的所有處理,對於許多問題來說,這都是個優雅的解決方案。
  • 供應商鎖定根本不存在。所有功能都通過API實現,只需要修改實現就可以在數週內完成不同雲供應商的遷移。
  • 最大的瓶頸來自數據。在不同雲環境中轉移大量數據異常困難。

原文鏈接: Nifty Architecture Tricks From Wix - Building A Publishing Platform At Scale(翻譯/童陽 責編/仲浩)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章