十億月PV網站祕訣:Reddit自失敗中總結的25條經驗

csdn發表於2013-09-06

  Reddit前僱員Jeremy Edberg在RAMP會議上發表了主題為“Scaling Reddit from 1 Million to 1 Billion–Pitfalls and Lessons”的精彩演講,分享了知名社交網站Reddit的打造經驗。Jeremy現為Netflix可靠性架構師,更添為 Year One Labs的顧問;曾任Reddit首席架構師,兼技術、運營部門負責人,更早之前還效力於eBay及Sendmail。

  近日HighScalanbility創始人Tod Hoff對該講話進行了總結,並基於Netflix做了相應的對比,以下為譯文:

  首先,一些值得關注的觀點:

  1. 將SSD看做便宜的RAM,而不是磁碟。在Reddit磁碟都更換為SSD之後,伺服器的數量從12臺減少到了1臺,並且有資源結餘。SSD是比磁碟貴4倍,但是你得到了16倍以上的效能,值得投入。

  2. 給使用者動手空間,看看他們都在做什麼,然後將好的東西加入到特性裡面。Reddit從使用者的身上學到了太多東西,網站的平穩執行有很大一部分歸功於使用者。通過使用者你可以瞭解很多未知卻非常有價值的東西,比如開始被比作社群笑話的Reddit Gold服務;當被Reddit做成產品後,深的使用者歡心。

 3. 開始時並不需要一個可擴充套件架構。未來的特性集肯定無法在開始被預測,所以有充足的時間去弄清擴充套件問題。隨著網站的發展,系統將被更清晰的認知,擴充套件性問題也將迎刃而解。

 4. 將未登入使用者作2等公民對待。未登入使用者遠離快取,讓Akamai首當其衝,效能將得到大幅提升。

  這樣的點還有很多,下面就看一下Jeremy Edberg在不斷失敗中提取的寶貴經驗:

 統計

  1. 流量每15個月翻一倍

十億月PV網站祕訣:Reddit自失敗中總結的25條經驗

  2. 如上圖所示,Reddit 8月的統計為:來自177個不同國家,67,328,706 UV及4,692,494,641PV。這個講話結束在10億PV這個點。

  3. 28個員工

  4. 每個員工大概負責2400萬UV。

  5. 上萬個志願版主

 6. 在2012年,Reddit使用 240個伺服器支撐每月20億的PV及2TB的PostgreSQL資料。所有高流量資料都從EBS(Elastic Block Store)轉移到Local Ephemeral Disk。

 故事的起源

  1. Reddit起源於2005年,開始的想法是訂餐服務,並未獲得Y Combinator的青睞。再次來到Y Combinator與Paul Graham詳談時,他們提出了建立整個網際網路首頁的創意。也就是現在的Reddit,當然不那個時候他們還不瞭解Digg。

  2. 網站開始託管在一個資料中心,然後逐漸過渡到EC2。

  • EC2在2006年首次被採用,主要使用S3儲存和服務日誌
  • 2007年使用S3儲存縮圖
  • 2008年使用EC2做批處理,使用VPN與資料中心連線
  • 2009年使用EC2服務整個網站。其花費整整1天的時間將所有資料遷移到EC2,Data Gravity一個很好的示例

 EC2

  1. EC2決策制定的積極因素

  • 不想租更多的機櫃及購買更多的伺服器
  • 資料中心規模擴充套件太快,並且無法在早期做增長預測
  • 對一個4人團隊來說,使用EC2更具成本效益,EC2比舊金山的資料中心便宜29%

  2. EC2並非一直無往不利。你需要忍受更高的網路延時及吵鬧的“鄰居”,因此必須早做打算,好處是可以按需擴充套件。

  3. EC2上資源限制記錄

  • 所有資源都存在單賬戶限制
  • Amazon有時候並未認識到一些來自他們的限制
  • 追蹤限制,並在需要之前克服
  • 捕獲異常,瞭解限制的臨界點

 架構

  1. Reddit的架構非常簡單的。使用者連線到一個與應用程式層通訊的web層,應用程式層則負責與memcache、Cassandra及PostgreSQL通訊。PostgreSQL使用了主-從配置,一個批處理系統通過Cassandra及PostgreSQL實現。

  2. 相比起來,Netflix使用了一個面向服務的架構,元件間通訊通過REST API實現

  • 優勢:易於擴充套件,因為擴充套件往往只是針對某個服務進行;易於容量規劃;更容易確定問題所在,因為他們都通過REST呼叫隔離;作用域變窄;更有效的本地快取。
  • 劣勢:需要在不同服務上工作的多個開發團隊或開發者,因此需要很多人力;需要防止工作重疊的通用平臺;對小團隊來說,初始的開銷太大了。

  3. PostreSQL是個非常好的資料庫,具備完美及飛速的鍵值儲存。

  4. Email是個不小的挑戰。投遞正確性難以保障。開始時使用自己的郵箱伺服器,現在已經轉向電子郵件服務提供商。

  5. 佇列是“救世主”。在做元件間工作傳遞時,將其放入一個佇列,將是一個非常不錯的小緩衝區。(Reddit使用RabbitMQ支撐佇列)

  6. 混合使用Nginx和HAProxy。許多傳輸是相互的,為了負載均衡,在Nginx無法處理時果斷轉向HAProxy。它使用L7負載均衡,而Nginx仍然用來終止SSL及服務靜態內容。

 程式碼

  1. 框架。開始時,使用的是Pylons(Django太慢了),一個基於Python的框架。確實易於起步,然而很快就被迫放棄,因為它們不符合你的用例。Pylon被做了太多的修改以至於無法更新到下一個版本,這個問題現在已經被修復了,所以還會再次使用Pyramid(pylon的新名字)。

  2. 基於事件還是執行緒?基於執行緒更好做容量規劃,但是執行緒池的容量需要投入很多的精力。基於事件,可以獲得更多的連線,但是你必須花時間去做好棘手問題凸現的準備。

  3. 開源是極好的。Reddit基於開源打造,付費軟體並不一定是個很好的決策,特別在起步階段。

 資料

  1. 資料是最寶貴的財產。類似Facebook、Google及Flicr都是建立在資料之上。

  2. 以資料為中心。圍繞資料建立應用程式,也就是應用程式需要繞資料運作。資料建立了一個重力井,所有的一切都需要向它靠攏,因為資料是最難移動的。資料集越大,遷移就越困難。如果將現在的Reddit搬離EC2,將造成非常大的開銷,這也是為什麼EC2在資料傳入時是免費的,讀出時卻是收費的,因為他們企圖將你所有資料都帶入雲中。

  3. 關係型資料庫和非關係型資料庫。大部分Reddit資料都是鍵值型的,儲存於PostgreSQL。基於事務的需求及易於分析,所有涉及金錢的處理都使用了關係型資料庫。

  4. 鐵打的PostgreSQL。PostgreSQL非常可靠,使用至今未發現其自身問題。如果真的出問題了,肯定由其它事件引起,比如使用Python編寫的備份系統。之所以PostgreSQL的使用場景多於Cassandra,因為Cassandra出現的比較晚。再加上PostgreSQL確實非常的快,並且原生支援KV。

  5. 分片。寫操作被分佈到4個主資料庫: 連結、 賬戶、subreddit、評論、投票及雜項。

  • 每個都有從節點。投票使用了1主+1從模式,而評論則是1主+12從
  • 儘可能的避免從主資料庫中讀取,直接在從節點上讀取,從而讓主節點專注於寫操作
  • 客戶端庫將負責從節點的負載平衡,在某個從節點繁忙時會自動選取另一個
  • 編寫了資料庫訪問層“thing”
  • 這個組合使用了很長一段時間:結合分片資料庫、從讀並且監視從讀效能以更好的均衡負載

  7. Cassandra

  • 寫入速度快,否定查詢速度快,易擴充套件,沒有單點故障
  • 在Netflix每個資料都會被分配到3臺主機上,如果1臺主機故障,餘下的可以繼續執行。
  • 將投票資料遷移至Cassandra讓Reddit獲益不淺:Cassandra布隆過濾器提供了非常快的否定查詢,對於評論來說,可以非常快的查詢出沒投票的評論,這樣反的答案將非常快的出現。( 更多細節

 社交

  1. 2008年的Reddit是開源的

  • 使用者可以檢視原始碼,然後確定沒有投票干預成分存在
  • 使用者可以新增自己一直想要的特性,Reddit就會支援它,當然這對不想寫程式碼的人毫無作用
  • 招聘。因為程式碼為許多人知曉,所以就更容易招聘瞭解程式碼的人,這個理論通常被用於創意推銷

  2. 蠕蟲事件。有人發現瞭如何通過給頁面注入javascript來編寫蠕蟲,雖然無意傳播但是已經洩露。而那天,剛好是Reddit一個創始人的大婚之日,整個團隊都在一架飛機上往回趕。然而不想一個使用者已經設計好了阻止蠕蟲傳播的補丁,並將之開源,在最危急的時候幫助到了社群。

 Reddit如何賺錢

  1. Sidebox廣告、自助式廣告、商品、Reddit Gold 服務、市場。

  2. 需要注意的是 Reddit尚未盈利,它同樣帶給我們一個問題——像Reddit這樣的網站是否可以通過雲來盈利?

  3. 同樣需要注意的是Reddit已不再屬於Condé Nast,也就是它獨立了。

 曾犯過的錯誤

  1. 未考慮遷移到EC2的延時。資料中心機器間訪問延時是亞毫秒級,所以針對一個頁面負載訪問1000次memcache也是可行的。然而在EC2中就不行了,memcache訪問時間延長10倍至毫秒級,這就讓老方法並不適用。應對方法是對memcache進行批量訪問,這樣一個請求將返回大量的結果。

  2. 未履行的承諾。Amazon不總是遵循承諾,並一遵循承諾為目標。要學會與故障周旋,而不是去修復。

  3. 不要怕使用新產品。Cassandra採用時,還處開發階段,雖現在發展不錯,但仍不乏問題。

  4. 在發往客戶端前,是否需要儘可能的簡化工作。在推送到客戶端之前,伺服器做了很多的頁面渲染。Facebook在這方面的經驗非常豐富,你得到一個擁有許多div及API(用於填充div)的矩形,這也是Reddit想盡快實現的地方。這樣會讓應用有更好的擴充套件性,同樣幫助到了除錯,因為很容易確定是哪個API產生了問題。

  5. 沒有足夠的監視,使用的唯一監視系統並不適合虛擬化場景。開始時使用的是Ganglia,它提供了非常不錯的圖形,但是難以使用並且變化的非常快,特別是在例項變化不斷的虛擬化環境中。

  6. 沒有給資料設定生命週期。在Reddit ,評論並沒有一個到期時間。他們已經著手限制老評論的投票,以及舊主題評論。這就導致了資料的一直增長,直到資料庫難以支撐熱資料的儲存。

  7. 沒有使用一致性雜湊。當給快取雜湊時,問題就卡在想為快取增加容量的情景——因為所有資料都在一個快取上,或者你需要雜湊太多快取。在快取增加後,無法再平衡。一致性雜湊就是問題的解決方法之一,他們通過遷移到Cassandra解決了這個問題。

 經驗教訓

  1. 擴充套件的關鍵就在於先使用者發現瓶頸所在

  2. 使用proxy非常有益於擴充套件。使用者可以通過URL被路由,Reddit擁有一個可以監視每個傳送給服務的URL長度。給流量的速度分級,基於響應速度的平均值去拆分流量是個巨大的提升。

  3. 自動化一切。如果可以像對待程式碼一樣去對待基礎設施,那麼工作將非常輕鬆,所有基礎設施最好能自動開啟和關閉,並且自動配置。

  4. 開始時並不需要建立一個可擴充套件架構。因為在初期你根本不知道最終的特性集,所以你有很多的時間來解決擴充套件問題。隨著網站的增長,你將清晰的發現問題所在。

  5. 在開始時並不需要使用一個面向服務的架構。將它做為目標,在網站發展到中等規模時可以去實現,否則只會帶來更多的開銷。

  6. 不必刻意追逐潮流,但是偶爾試下也不錯,比如node.js。

  7. 限制一切。時常發生的事情需要加上限制,並根據需求抬高或者放低。如果超出限制,需阻止使用者已保證服務的正常運作。

  8. 長遠的計劃。設計時總是假設當下做的事情以後會有更多,應用程式伺服器、資料庫、快取。開始時就假設不會只有1個,那麼以後的橫向擴充套件會容易很多。

  9. 將Python使用C來重新編碼。隨著Reddit不停擴充套件以追求更快的速度,他們使用C來重新編碼了經常用到的功能(之前用的是Python),特別是過濾器、Markdown渲染以及memcache呼叫。這時Python作為膠水語言的好處就出來了,呼叫C時非常簡單且效率。

  10. 儘量保持無結構化模式,這將讓服務很容易新增特性——在不更改表格的情況下就可以增加屬性。

  11. 資料的生命週期。對舊主題進行鎖定,然後建立一個完整的呈現頁面並快取,這樣就可以保證資料庫不會被舊資料淹沒。同時,停止舊評論的投票及舊主題的評論,使用者一般很少發現。

  12. 將SSD看做便宜的RAM,而不是磁碟。當Reddit將磁碟都換成SSD後,伺服器數量從12臺減少到了1臺,並且還有資源結餘。SSD是比磁碟貴4倍,但是得到的卻是16倍效能,值得投入。在Netflix與Reddit,一些最大的Cassandra都使用上了SSD,各方面得到了很大的提升。

  13. 每個工具都有特定的用例。Memcache無法持久化,但是卻非常快,所以投票資料就儲存在那裡以保證頁面的飛速渲染。Cassandra可以持久化並且很快,同時布隆過濾器還提供了快速的反查詢,所以當資料不在快取中時用它來儲存投票的副本非常合適。PostgreSQL是可靠的關係型資料庫,所以用它來作為Cassandra的備份儲存投票資料,以及用作需要相關性的批處理操作。

  14. 將未登入使用者視為2等公民。開始時這些使用者佔了網路流量的80%,至今仍有50%之巨。讓未註冊使用者遠離快取,Akamai首當其衝,效能將得到大幅提升。附帶的好處是,如果Reddit當機了,未登入使用者甚至毫無所知。

  15. 將一切都放到佇列中。投票、評論、縮圖建立、預計算查詢、垃圾郵件處理及修正,佇列可以讓你在監視長度時發現問題所在。附加好處是,佇列可以讓問題對使用者透明;比如佇列中的投票請求,如果沒有立即生效的話不會有任何人注意到。

  16. 將資料儲存在多個可用區域

  17. 避免將網站放到一個單例項上

  18. 頻繁的抓取EBS磁碟快照

  19. 不要在例項上儲存祕鑰

  20. 通過Security Group劃分功能

  21. 提供一個API。程式設計師將在你的平臺上開發,比如Reddit的iPhone應用就是使用者通過API建立的。

  22. 在社群中保持一定的活躍度。Reddit管理員經常在論壇現身並參與互動,這點深受其使用者的喜愛。

  23. 讓使用者為你做事。人氣網站總是不乏欺詐、垃圾郵件等問題,而在Reddit這項工作由上萬個志願者完成,他們仔細的處理了大多數的垃圾郵件問題。這個工作模式順利的難以置信,同時這也是Reddit的團隊可以維持很小的原因。

  24. 給使用者動手空間,看看他們都在做什麼,然後將好的東西加入到特性裡面。比如賦予使用者給subreddit新增CSS的能力,選擇好的功能,併為每個使用者都新增。這同樣讓使用者樂於在Reddit上做些東西,讓他們滿足於這種控制感。

  25. 聽使用者的話,使用者將告訴你許多想知道但還不知道的事情。比如,在社群中Reddit Gold服務以笑話的形式開始,但是做成產品後卻深受使用者喜歡。

  原文連結: Reddit: Lessons Learned from Mistakes Made Scaling to 1 Billion Pageviews a Month

相關文章