Reddit月瀏覽量從百萬擴容到十億的陷阱和教訓

dryrun發表於2013-07-04

伯樂線上導讀:Reddit[1]是一個社交新聞網站。使用者可以將網際網路上搜集或原創的圖片或材料以帖子形式釋出於網站上。而後其他使用者可以投票,投票的結果將作為帖子排名的依據。

Reddit 網站的第一位領薪僱員傑里米·埃德伯格在RAMP[2]討論會上做了一次出色的演講 ,他教給我們很多關於如何建立一個成功的社交網站。這兒可以看到視訊。

傑里米借用了(宗教裡對比)罪惡和美德的方式來總結經驗教訓,他分享了在擴充套件Reddit過程中所犯錯誤的例子,也可以看到他們同樣做了很多正確的事情。不過有點令人吃驚的是,傑里米現在是Netflix[3]的可靠性架構師。所以這篇文章中也有Netflix的一些經驗。(感謝 dryrun 的熱心翻譯和詳細的譯註,感謝@戰鬥的那美剋星人 的重審校對。如果其他朋友也有不錯的原創或譯文,可以嘗試提交到伯樂線上。)

我完全認可的一些經驗教訓:

  • SSD[4]看做是便宜的記憶體[5],而不是昂貴的硬碟。當我們為了資料庫的效能將reddit從普通硬碟轉移到SSD後,我們的伺服器數量從12臺降低到1臺(這個很可能是個比例資料,譯者),並且還有很大的富餘。SSD雖然貴了四倍,但是你會得到16倍的效能提升,這麼做是很值得的。
  • 給使用者一些權力,看看他們怎麼做,然後考慮把好的點子加入到網站功能中來。用使用者讓reddit學到了很多東西,並且,使用者很大程度上提升了網站的流暢度(文後會有描述使用者如何協助網站的順利運轉,譯者),這個是我眾多收穫中很重要的一點。使用者會告訴你很多你不知道的事情。關於這點,reddit gold是個很好的案例,這個專案開始只是社群裡的一個玩笑,後來它被做成了產品,並深得所有使用者喜愛。
  • 專案之初關於可擴充套件性架構的考慮其實是沒有太多必要的。一開始時你不知道什麼會是你的功能集,所以你也不會知道你有哪些擴充套件問題。隨著你的網站增長,你可以瞭解哪裡將存在擴充套件問題。
  • 把未登入使用者當作二等公民。給未登入使用者返回快取內容,Akamai(美國著名CDN服務提供商)[6]首當其衝,reddit壓力大減,這種做法帶來巨大的效能提升。

 

還有很多。我們從早期擴充套件reddit的錯誤中學到許多經驗教訓,下面是我的觀點的一些解釋和展開:

統計

  • 流量大約每15個月增加1倍。
  • 上個月(8月份),來自177個不同國家的 73,293,644 名獨立訪客檢視了reddit的 4,885,611,148 個頁面。“10億的PV承載能力”來自這個資料。不確認現在的架構是否會有很大不同。
  • 28名僱員。
  • 每名僱員應對大約240萬獨立訪客。(連結
  • 數以千計的版主。
  • 在2012年時,他們用240臺伺服器,支撐每月20億頁面瀏覽量和Postgres[7]裡的2TB資料。所有高流量壓力資料從EBS[8]轉移到本地臨時磁碟。

 

起源故事

  • Reddit始於2005年。在帶著“通過文字來點餐”的想法去Y Combinator[9]被拒絕後,他們和Paul Grahm討論並著手開始建設網際網路網頁。這就是reddit。那時他們並不知道Digg[10]
  • 從資料中心開始,隨後將功能逐步轉移至EC2[11]

1 在2006年在EC2上開始使用S3[12]提供標識的儲存和服務。

2 2007年開始使用S3支援縮圖。

3 2008年使用EC2提供批處理服務,並通過vpn通道連線資料中心。

4 2009年使用EC2服務整個網站。網站停運一天,將資料全部遷移到EC2。稍後會談到著名的資料重力例子。

 

EC2

  • 遷移到EC2上的動機

5 堆疊機架不好玩。不想租用更多的機櫃和購買更多的伺服器。

6 資料中心增長過快,增速在早期無法預測。

7 4人一組的開發團隊的使用價格,EC2比在舊金山的資料中心成本節約29%。

  • EC2不是靈丹妙藥。你要經受更高的網路延遲和嘈雜的鄰居,所以計劃好應對方案。好處是你可以隨時按需擴容。
  • 持續跟蹤EC2的資源限制

8 所有資源都有賬戶配額。

9 甚至亞馬遜自己都不清楚什麼地方可能有配額。

10 跟蹤配額,並在需要的時候提升。

11 捕獲異常以確認什麼時候又達到了配額上限。

 

架構

  • Reddit的架構很簡單。使用者連線網路層,網路層對話應用層。應用層跟memcache[14],Cassandra[15],以及Postgres對話。Postgres使用主從配置。批處理系統使用Cassandra和Postgres。
  • 對比netflix,使用面向服務架構,所有元件之間通過REST API進行互動。

12 優點:更容易自動調節,因為只是有問題的服務需要調節;更容易規劃容量;問題也更容易定位,因為它們在REST呼叫背後都是孤立的;改動和升級產生的影響範圍更小;更高效的本地快取。

13 缺點:需要多個開發團隊或開發者來跟進多個服務,因此你需要更多的人;需要一個共同的平臺以防重複工作;對剛起步的小團隊來說太多的間接支出。

  • PostgreSQL是一個出色資料庫。它提供很棒的、很快的鍵值儲存。
  • 電子郵件是一個很難的問題。很難正確被送達。開始是使用自行開發的郵件系統,但是今天可能會去選擇一個電子郵件服務提供商。
  • 佇列是救世主。元件之間傳遞任務時,把它放到一個佇列。你會得到一個不錯的小緩衝區。(Reddit使用RabbitMQ[17]作為訊息佇列。)
  • 混合HAProxy[18]Nginx[19]。一些流量被引導到它們中的一個。在嘗試Niginx(遇到故障)後,負載均衡會選擇HAProxy。它使用L7[20]做負載均衡。Nginx仍被用來完成SSL[21]請求和服務靜態內容。

 

程式碼

  • 框架。最開始,使用了一個基於Python的架構(Django[23]太慢了)Pylons[22]。對Pylons進行定製以使上手變得容易,不過最終因為使用場景差異較大而放棄。對Pylon做了很大改動,結果最後使得它難以升級到新版本(現在修復了)。會將再次使用金字塔的(Pylons的新名字)。
  • 基於執行緒還是事件?基於執行緒可以提前以排列大小,但大小可能是錯誤的。基於事件可以處理更多連線。但是當你碰壁時就只能碰壁。你想花更多時間來規劃你得執行緒池大小,還是就突然碰壁?
  • 開源很不錯。Reddit建立在開源基礎上。不用為軟體付錢很不錯,特別是在起步階段。

 

資料

  • 資料是公司最重要的資產。Facebook,Google和Flickr[24]等公司都是建立在資料之上。
  • 資料重力。資料放在哪兒,應用就部署到哪兒。思路是應用隨資料調整。資料建立了重力井,其他東西需要圍繞它展開,因為資料是最難移動的。資料越多就越難移動。目前,從EC2匯出資料的成本太大了。這就是為什麼EC2允許你免費匯入資料,當你匯出時向你收費。他們希望你把你所有的資料放在雲中。
  • 關係與非關係。Reddit裡的大部分資料是以鍵值方式儲存在Postgres。一切涉及金錢交易的資料都被儲存在關聯式資料庫,這樣可以保障更好的事務性和更容易進行分析。
  • Postgres很穩定。它堅如磐石,他們從未有過自身問題。如果他們有問題,那也是使用上的問題,例如用Python編寫的呼叫系統。因為,很難找到Postgres專家。
  • Postgres被選為鍵值儲存,因為當時還木有Cassandra。另外,Postgres的速度非常快,而且現在原生地支援鍵值(KV)。
  • 分割槽。寫入被分割的四個主資料庫:連結,帳戶,subreddits[25],評論,投票,以及雜項。

14 每個資料庫都有主從設計。投票用資料庫是一主一從。而註釋用資料庫是一主12從。

15 儘可能避免從主資料庫讀取,而是直接從從屬資料庫讀取,保持主資料庫只進行寫操作。

16 客戶端庫將在從屬資料庫之間進行負載平衡,如果一個從屬資料庫處於忙狀態,則嘗試使用另外一個從資料庫。

17 編寫一個叫“thing”的資料庫訪問層。

18 這種方式支撐了很長時間,包括資料庫切分、從資料庫讀取、跟蹤從資料庫的效能用於更好的負載均衡。

  • Cassandra

19 快速寫入,快速反查,簡單的增量可擴充套件性,無單點故障。

20 在Netflix資料被分散式部署在三個不同的區域。完整的資料副本同時存在三個區域中。即使一個區域丟失,依然可以正確執行。

21 將“投票”相關資料切換到Cassandra是reddit的一個巨大成功。Cassandra的布隆過濾器(Bloom Filters[26])使快速反查成為可能。它能很快識別哪個評論你沒有投票,所以反查結果會很快返回。(更多關於這個話題

 

社交

  • 2008reddit是開源的

22 使用者可以讀取程式碼從而得知篡改投票是不存在的。

23 使用者可以新增他們想要的功能,reddit會接受它。這個其實行不通,因為人們並不真的想寫程式碼。

24 招聘。其他人知道這程式碼,所以更容易僱人。

  • 蠕蟲事件。有人指出在頁面中注入額外的JavaScript的方式可以製造蠕蟲病毒。如何出現已無關緊要,但是蠕蟲事件失控了。在一個創始人的婚禮當天,整個團隊乘一架飛機從婚禮現場趕回。一個使用者已經預先提交了一個可以組織蠕蟲蔓延的補丁。程式碼開源使社群在危急時刻提供了很大幫助。

 

Reddit如何掙錢?

  • 側欄廣告,自助式廣告,商品,reddit gold,市場。
  • 需要注意的是reddit是尚未盈利(連結)。這帶來了一個問題,像reddit這樣的網站,什麼時候能在雲端盈利?
  • 還要注意的是,reddit已不屬於Condé Nast[27]了,所以它是獨立的。(連結

 

錯誤

  • 沒有考慮到遷移到EC2後增加的延遲。在資料中心,機器之間的響應是亞毫秒級的,一個頁面的載入時間內可以進行1000次memcache訪問。在EC2上並非如此。 Memcache訪問時間增加了10倍,到毫秒級,使得之前的邏輯基本不可用。修復方法是在一個memcache請求內進行批量操作。
  • 只是承諾。亞馬遜並不總兌現承諾和解決問題。所以設計的時候需要考慮繞過而不是解決。 (這裡沒有提到,也許EBS?)
  • 在生產中使用更穩定的產品。我們在Cassandra的開發階段就開始使用它。現在真的很棒,但那時它是個問題專業戶。
  • 本應該更早將負載轉移到客戶端。伺服器做了很多的頁面渲染,其中一些本可以交給客戶端去做。 Facebook是這方面的大師。返回一個提前規劃好的空間和很多的div,以及通過API呼叫來填充他們。這就是他們起初所希望的reddit。它本可以擴充套件得更好。它還有助於除錯,因為很容易確定哪個API呼叫出了問題。
  • 不具備足夠的監控,使用的監控系統並不能很好支援虛擬化。一開始用的是Ganglia[28],倒是有很好的圖形介面,但很難使用,而且變化太快,特別是在一個例項會不斷建立和消亡的場景下。
  • 資料沒有過期時間。 你可以在reddit看到最初的那些評論被挖墳。他們已經開始著手做一些限制工作,你不能再給舊評論投票,或給舊帖新增評論。挖墳的問題會導致資料隨著時間的推移不斷增長,使得在資料庫儲存熱點資料的難度越來越大。
  • 沒有使用一致性雜湊演算法。當hash一個快取時問題是,如果你需要新增更多的快取,你會被卡住,因為所有的資料會命中一個hash或者許多你正在雜湊的快取。當增加快取時你無法在此平衡。一致性雜湊演算法是解決這個問題的一個方法。遷移到Cassandra使這個問題被解決。

 

經驗教訓

  • 擴充套件的關鍵是現於使用者發現瓶頸。
  • 使用代理是擴充套件的巨大福音。根據使用者命中的URL進行路由。 Reddit有一個系統,監控每個URL抵達服務的時長(從請求發起到到達服務的時間,譯者)。人們被放進不同的線路。慢流量去一個地方,快的去另一個。基於響應速度的流量分割是一個巨大的改進。
  • 自動化所有事情。像對待你的程式碼一樣對待你的基礎架構,你的生活會容易得多。一切都應該自動上線,自動配置。
  • 沒有必要從一開始就建立一個可擴充套件的架構。一開始時你不知道什麼會是你的功能集,所以你也不知道你有會有哪些擴充套件問題。隨著你的網站增長,你可以瞭解到哪裡將是擴充套件問題。
  • 剛起步時不要使用面向服務的架構。記住,當發展到中等規模時你可以去實現它;前期只會帶來很多額外的開銷。
  • 不要跟隨潮流。有時候潮流是對的,例如node.js。
  • 給所有東西加個限制。給反覆發生的事情設定一個上限,並根據需要提高或降低限制。如果超過限制,阻止使用者以。這樣可以保護正常服務。例如為subreddits上傳檔案標識。有使用者指出他們可以上傳很大的檔案並損害系統。也不要接受巨大的文字。會有人指出如何給你傳送一個5GB的文字。
  • 長遠計劃。在設計時總是假設將有一大堆事情需要你做。應用伺服器,資料庫,快取。總是在開始時就假定你有一個以上的事情。這樣,未來的橫向擴充套件會更容易。
  • 用C重寫Python函式。在reddit擴充套件中,為了獲取速度,他們找出Python程式碼裡重複次數最多的函式,並用C重寫。比如過濾器,markdown渲染,memcache呼叫。Python的一個好處是可以很容易並高效地呼叫C。
  • 儘可能保持無結構模式。這樣的話,可以很容易地增加新的功能。你所要做的就是新增新的屬性,而無需改變資料表結構。
  • 資料過期。鎖定舊帖和建立一個完整渲染的頁面並快取它。這個可以用來應對大規模舊資料衝擊資料庫的場景。同樣的,不要允許在舊的評論上投票,或給舊帖新增評論。使用者很少會關心這個。
  • 把SSD[4]看做是便宜的記憶體[5],而不是昂貴的硬碟。當我們為了資料庫的效能將reddit從普通硬碟轉移到SSD後,我們的伺服器數量從12臺降低到1臺(這個很可能是個比例資料,譯者),並且還有很大的富餘。SSD雖然貴了四倍,但是你會得到16倍的效能提升,這麼做是很值得的。
  • 每個工具都有不同的使用場景。Memcache不提供永續性保障,但是會非常快,所以投票資料儲存在那裡,以使渲染頁面儘可能的快。Cassandra持久,快速,並能提供快速的反查詢,因為其布隆過濾器,所以它適合提供memchche裡投票資料副本的持久化。 Postgres是堅如磐石而且是關係型的,所以用作備份Cassandra投票(如果需要,Cassandra中的所有資料可以從Postgres恢復),也可以做批量處理,有時這需要關係的能力。
  • 將未登入使用者當作二等公民。未登入使用者之前曾佔據約80%的流量,現在是接近50%。總是給未登入使用者提供快取內容,Akamai承載了大部分Reddit的流量,帶來巨大的效能改進。附帶的好處是如果reddit當機,你不登入的話,你可能永遠不會知道。
  • 把一切都放入一個佇列。投票,評論,建立縮圖,預計算查詢,郵件處理和更正。通過監控佇列長度,你可以知道什麼時候佇列可能存在問題了。附帶的好處是佇列隱藏了使用者的問題,因為諸如投票請求的事情都在排隊,投票不做提交時使用者並不會馬上發現。
  • 把資料分散到多個可用區域進行儲存。
  • 避免在單一例項上儲存狀態。
  • EBS磁碟頻繁建立快照。
  • 不要在例項上儲存金鑰。亞馬遜現提供了一個服務。
  • 基於安全分組分解功能
  • 提供API。程式設計師將會在你的平臺上做東西。例如,reddit的iPhone應用程式,就是其他人用公開的API製作的。
  • 在自己的社群保持活躍。Reddit的使用者喜歡reddit的管理員在自己網站上活躍,並與他們互動。
  • 讓使用者為你工作。有使用者輸入的網站,總是有作弊、垃圾郵件和欺詐這樣一些問題。Reddit大部分管理的工作是由成千上萬的志願者來完成的,比如他們處理大多數的垃圾郵件問題。這種方式運轉得非常好,是reddit的可以保持小團隊的原因之一。
  • 給使用者一點權利,看他們用它做什麼,並好東西變成功能。例如,當新增了給subreddits增加CSS得能力時,他們看到人們在做什麼,增加了許多通用的東西作為大家的功能。這也使得使用者能在Reddit上做東西而興奮,因為他們喜歡那種操控感。有很多其他的例子。
  • 傾聽你的使用者。使用者會告訴你很多你不知道但是你可能想知道的東西。例如,reddit gold在社群裡以一個笑話開始。後來他們把它做成了產品,使用者也很喜歡。

 

 

譯註:

1. Reddit是一家美國社交新聞網站Reddit.com。
2. RAMP是一個所有創業者在擴大經營規模前想要參加的討論會。
3. Netflix是一家美國公司,提供網際網路隨選流媒體播放、線上出租業務。
4. SSD即Solid State Disk固態硬碟。
5. RAM即Random Access Memory隨機訪問儲存器。
6. Akamai是一家美國內容分發網路(CDN)服務商。
7. Postgres即PostgreSQL, 是一個自由的物件-關聯式資料庫伺服器(資料庫管理系統)。
8. EBS即exclusion basis system,動態金鑰管理方法。
9. Y Combinator是一家以投資種子階段初創公司為業務的創投公司。
10. Digg即“掘客”,或者“頂格”,美國公司,2012年被紐約科技開發公司Betaworks收購。
11. EC2即亞馬遜彈性計算雲(Elastic Compute Cloud),是一個讓使用者可以租用雲端電腦執行所需應用的系統。
12. S3即亞馬遜簡易儲存服務(Simple Storage Service),由亞馬遜網路服務系統提供的線上儲存服務。
13. VPN即虛擬專用網路(Virtual Private Network),是在公用網路上建立專用網路的技術。
14. Memcache是一個高效能的分散式的記憶體物件快取系統。
15. Cassandra是一套開源分散式NoSQL資料庫系統。
16. REST即表徵狀態轉移(Representational State Transfer)是Roy Fielding博士在2000年博士論文中提出來的一種軟體架構風格。
17. RabbitMQ是流行的開源訊息佇列系統。
18. HAProxy提供高可用性、負載均衡以及基於TCP和HTTP應用的代理。
19. Nginx即engine x,是一個高效能的 HTTP和反向代理伺服器。
20. L7即Layer7,是網路層協議的指令碼檔案。
21. SSL即Secure Sockets Layer安全套接層,是為網路通訊提供安全及資料完整性的一種安全協議。
22. Pylons是一個開放原始碼的Web應用框架,使用python語言編寫。
23. Django是一個開放原始碼的Web應用框架,使用python語言編寫。
24. Flickr是雅虎旗下圖片分享網站。
25. Subreddit 是reddit上一個定製的子論壇。
26. Bloom Filter即布隆過濾器,是一個很長的二進位制向量和一系列隨機對映函式。
27. Condé Nast即康泰納仕,是一個總部位於美國紐約市的國際期刊出版集團。
Ganglia是UC Berkeley發起的一個開源叢集監視專案。

相關文章