1. 程式人生 > >優酷、YouTube、Twitter及JustinTV視訊網站架構設計筆記

優酷、YouTube、Twitter及JustinTV視訊網站架構設計筆記

               

本文是整理的關於優酷、YouTube、Twitter及JustinTV幾個視訊網站的架構或筆記,對於不管是視訊網站、入口網站或者其它的網站,在架構上都有一定的參考意義,畢竟成功者的背後總有值得學習的地方,雖然有些文章的發表時間有點久了,但是看看對開闊視野還是有幫助的。

優酷視訊網站架構

一、網站基本資料概覽據2010年統計,優酷網日均獨立訪問人數(uv)達到了8900萬,日均訪問量(pv)更是達到了17億,優酷憑藉這一資料成為google榜單中國內視訊網站排名最高的廠商。硬體方面,優酷網引進的戴爾伺服器主要以 PowerEdge 1950與PowerEdge 860為主,儲存陣列以戴爾MD1000為主,2007的資料表明,優酷網已有1000多臺伺服器遍佈在全國各大省市,現在應該更多了吧。二、網站前端框架

從一開始,優酷網就自建了一套CMS來解決前端的頁面顯示,各個模組之間分離得比較恰當,前端可擴充套件性很好,UI的分離,讓開發與維護變得十分簡單和靈活,下圖是優酷前端的模組呼叫關係:優酷前端的模組呼叫關係這樣,就根據module、method及params來確定呼叫相對獨立的模組,顯得非常簡潔。下面附一張優酷的前端區域性架構圖:優酷的前端區域性架構圖 三、資料庫架構應該說優酷的資料庫架構也是經歷了許多波折,從一開始的單臺MySQL伺服器(Just Running)到簡單的MySQL主從複製、SSD優化、垂直分庫、水平sharding分庫,這一系列過程只有經歷過才會有更深的體會吧,就像MySpace的架構經歷一樣,架構也是一步步慢慢成長和成熟的。1、簡單的MySQL主從複製:MySQL的主從複製解決了資料庫的讀寫分離,並很好的提升了讀的效能,其原來圖如下:
MySQL主從複製
其主從複製的過程如下圖所示:主從複製的過程但是,主從複製也帶來其他一系列效能瓶頸問題:-寫入無法擴充套件-寫入無法快取-複製延時-鎖表率上升-表變大,快取率下降那問題產生總得解決的,這就產生下面的優化方案,一起來看看。2、MySQL垂直分割槽如果把業務切割得足夠獨立,那把不同業務的資料放到不同的資料庫伺服器將是一個不錯的方案,而且萬一其中一個業務崩潰了也不會影響其他業務的正常進行,並且也起到了負載分流的作用,大大提升了資料庫的吞吐能力。經過垂直分割槽後的資料庫架構圖如下:MySQL垂直分割槽然而,儘管業務之間已經足夠獨立了,但是有些業務之間或多或少總會有點聯絡,如使用者,基本上都會和每個業務相關聯,況且這種分割槽方式,也不能解決單張表資料量暴漲的問題,因此為何不試試水平sharding呢? 3、MySQL水平分片(Sharding)這是一個非常好的思路,將使用者按一定規則(按id雜湊)分組,並把該組使用者的資料儲存到一個數據庫分片中,即一個sharding,這樣隨著使用者數量的增加,只要簡單地配置一臺伺服器即可,原理圖如下:
MySQL水平分片
如何來確定某個使用者所在的shard呢,可以建一張使用者和shard對應的資料表,每次請求先從這張表找使用者的shard id,再從對應shard中查詢相關資料,如下圖所示:使用者所在的shard但是,優酷是如何解決跨shard的查詢呢,這個是個難點,據介紹優酷是儘量不跨shard查詢,實在不行通過多維分片索引、分散式搜尋引擎,下策是分散式資料庫查詢(這個非常麻煩而且耗效能) 四、快取策略貌似大的系統都對“快取”情有獨鍾,從http快取到memcached記憶體資料快取,但優酷表示沒有用記憶體快取,理由如下:避免記憶體拷貝,避免記憶體鎖如接到老大哥通知要把某個視訊撤下來,如果在快取裡是比較麻煩的而且Squid 的 write() 使用者程序空間有消耗,Lighttpd 1.5 的 AIO(非同步I/O) 讀取檔案到使用者記憶體導致效率也比較低下。但為何我們訪問優酷會如此流暢,與土豆相比優酷的視訊載入速度略勝一籌?這個要歸功於優酷建立的比較完善的內容分發網路(CDN),它通過多種方式保證分佈在全國各地的使用者進行就近訪問——使用者點選視訊請求後,優酷網將根據使用者所處地區位置,將離使用者最近、服務狀況最好的視訊伺服器地址傳送給使用者,從而保證使用者可以得到快速的視訊體驗。這就是CDN帶來的優勢,就近訪問,有關CDN的更多內容,請大家Google一下。

YouTube網站架構

YouTube發展迅速,每天超過1億的視訊點選量,但只有很少人在維護站點和確保伸縮性。這點和PlentyOfFish類似,少數人維護龐大系統。是什麼原因呢?放心絕對不是靠人品,也不是靠寂寞,下面就來看看YouTube的整體技術架構吧。平臺1、Apache2、Python3、Linux(SuSe)4、MySQL5、psyco,一個動態的Python到C的編譯器6、lighttpd代替Apache做視訊檢視狀態1、支援每天超過1億的視訊點選量2、成立於2005年2月3、於2006年3月達到每天3千萬的視訊點選量4、於2006年7月達到每天1億的視訊點選量5、2個系統管理員,2個伸縮性軟體架構師6、2個軟體開發工程師,2個網路工程師,1個DBAWeb伺服器1,NetScaler用於負載均衡和靜態內容快取2,使用mod_fast_cgi執行Apache3,使用一個Python應用伺服器來處理請求的路由4,應用伺服器與多個數據庫和其他資訊源互動來獲取資料和格式化html頁面5,一般可以通過新增更多的機器來在Web層提高伸縮性6,Python的Web層程式碼通常不是效能瓶頸,大部分時間阻塞在RPC7,Python允許快速而靈活的開發和部署8,通常每個頁面服務少於100毫秒的時間9,使用psyco(一個類似於JIT編譯器的動態的Python到C的編譯器)來優化內部迴圈10,對於像加密等密集型CPU活動,使用C擴充套件11,對於一些開銷昂貴的塊使用預先生成並快取的html12,資料庫裡使用行級快取13,快取完整的Python物件14,有些資料被計算出來併發送給各個程式,所以這些值快取在本地記憶體中。這是個使用不當的策略。    應用伺服器裡最快的快取將預先計算的值傳送給所有伺服器也花不了多少時間。只需弄一個代理來監聽更改,預計算,然後傳送。視訊服務1,花費包括頻寬,硬體和能源消耗2,每個視訊由一個迷你叢集來host,每個視訊被超過一臺機器持有3,使用一個叢集意味著:   -更多的硬碟來持有內容意味著更快的速度   -failover。如果一臺機器出故障了,另外的機器可以繼續服務   -線上備份4,使用lighttpd作為Web伺服器來提供視訊服務:   -Apache開銷太大   -使用epoll來等待多個fds   -從單程序配置轉變為多程序配置來處理更多的連線5,大部分流行的內容移到CDN:  -CDN在多個地方備份內容,這樣內容離使用者更近的機會就會更高  -CDN機器經常記憶體不足,因為內容太流行以致很少有內容進出記憶體的顛簸6,不太流行的內容(每天1-20瀏覽次數)在許多colo站點使用YouTube伺服器  -長尾效應。一個視訊可以有多個播放,但是許多視訊正在播放。隨機硬碟塊被訪問  -在這種情況下快取不會很好,所以花錢在更多的快取上可能沒太大意義。  -調節RAID控制並注意其他低階問題  -調節每臺機器上的記憶體,不要太多也不要太少視訊服務關鍵點1,保持簡單和廉價2,保持簡單網路路徑,在內容和使用者間不要有太多裝置3,使用常用硬體,昂貴的硬體很難找到幫助文件4,使用簡單而常見的工具,使用構建在Linux裡或之上的大部分工具5,很好的處理隨機查詢(SATA,tweaks)縮圖服務1,做到高效令人驚奇的難2,每個視訊大概4張縮圖,所以縮圖比視訊多很多3,縮圖僅僅host在幾個機器上4,持有一些小東西所遇到的問題:   -OS級別的大量的硬碟查詢和inode和頁面快取問題   -單目錄檔案限制,特別是Ext3,後來移到多分層的結構。核心2.6的最近改進可能讓 Ext3允許大目錄,但在一個檔案系統裡儲存大量檔案不是個好主意   -每秒大量的請求,因為Web頁面可能在頁面上顯示60個縮圖   -在這種高負載下Apache表現的非常糟糕   -在Apache前端使用squid,這種方式工作了一段時間,但是由於負載繼續增加而以失敗告終。它讓每秒300個請求變為20個   -嘗試使用lighttpd但是由於使用單執行緒它陷於困境。遇到多程序的問題,因為它們各自保持自己單獨的快取   -如此多的圖片以致一臺新機器只能接管24小時   -重啟機器需要6-10小時來快取5,為了解決所有這些問題YouTube開始使用Google的BigTable,一個分散式資料儲存:   -避免小檔案問題,因為它將檔案收集到一起   -快,錯誤容忍   -更低的延遲,因為它使用分散式多級快取,該快取與多個不同collocation站點工作   -更多資訊參考Google Architecture,GoogleTalk Architecture和BigTable資料庫1,早期   -使用MySQL來儲存元資料,如使用者,tags和描述   -使用一整個10硬碟的RAID 10來儲存資料   -依賴於信用卡所以YouTube租用硬體   -YouTube經過一個常見的革命:單伺服器,然後單master和多read slaves,然後資料庫分割槽,然後sharding方式   -痛苦與備份延遲。master資料庫是多執行緒的並且執行在一個大機器上所以它可以處理許多工作,slaves是單執行緒的並且通常執行在小一些的伺服器上並且備份是非同步的,所以slaves會遠遠落後於master   -更新引起快取失效,硬碟的慢I/O導致慢備份   -使用備份架構需要花費大量的money來獲得增加的寫效能   -YouTube的一個解決方案是通過把資料分成兩個叢集來將傳輸分出優先次序:一個視訊檢視池和一個一般的叢集2,後期   -資料庫分割槽   -分成shards,不同的使用者指定到不同的shards   -擴散讀寫   -更好的快取位置意味著更少的IO   -導致硬體減少30%   -備份延遲降低到0   -現在可以任意提升資料庫的伸縮性資料中心策略1,依賴於信用卡,所以最初只能使用受管主機提供商2,受管主機提供商不能提供伸縮性,不能控制硬體或使用良好的網路協議3,YouTube改為使用colocation arrangement。現在YouTube可以自定義所有東西並且協定自己的契約4,使用5到6個數據中心加CDN5,視訊來自任意的資料中心,不是最近的匹配或其他什麼。如果一個視訊足夠流行則移到CDN6,依賴於視訊頻寬而不是真正的延遲。可以來自任何colo7,圖片延遲很嚴重,特別是當一個頁面有60張圖片時8,使用BigTable將圖片備份到不同的資料中心,程式碼檢視誰是最近的學到的東西1,Stall for time。創造性和風險性的技巧讓你在短期內解決問題而同時你會發現長期的解決方案2,Proioritize。找出你的服務中核心的東西並對你的資源分出優先級別3,Pick your battles。別怕將你的核心服務分出去。YouTube使用CDN來分佈它們最流行的內容。建立自己的網路將花費太多時間和太多money4,Keep it simple!簡單允許你更快的重新架構來回應問題5,Shard。Sharding幫助隔離儲存,CPU,記憶體和IO,不僅僅是獲得更多的寫效能6,Constant iteration on bottlenecks:   -軟體:DB,快取   -OS:硬碟I/O   -硬體:記憶體,RAID7,You succeed as a team。擁有一個跨越條律的瞭解整個系統並知道系統內部是什麼樣的團隊,如安裝印表機,安裝機器,安裝網路等等的人。   With a good team all things are possible。

Twitter網站架構

一、twitter網站基本情況概覽截至2011年4月,twitter的註冊使用者約為1.75億,並以每天300000的新使用者註冊數增長,但是其真正的活躍使用者遠遠小於這個數目,大部分註冊使用者都是沒有關注者或沒有關注別人的,這也是與facebook的6億活躍使用者不能相提並論的。twitter每月有180萬獨立訪問使用者數,並且75%的流量來自twitter.com以外的網站。每天通過API有30億次請求,每天平均產生5500次tweet,37%活躍使用者為手機使用者,約60%的tweet來自第三方的應用。平臺:Ruby on Rails 、Erlang 、MySQL 、Mongrel 、Munin 、Nagios 、Google Analytics 、AWStats 、Memcached下圖是twitter的整體架構設計圖:twitter的整體架構設計圖二、twitter的平臺twitter平臺大致由twitter.com、手機以及第三方應用構成,如下圖所示:twitter的平臺其中流量主要以手機和第三方為主要來源。Ruby on Rails:web應用程式的框架Erlang:通用的面向併發的程式語言,開源專案地址:http://www.erlang.org/AWStats:實時日誌分析系統:開源專案地址:http://awstats.sourceforge.net/Memcached:分散式記憶體快取組建Starling:Ruby開發的輕量級訊息佇列Varnish:高效能開源HTTP加速器Kestrel:scala編寫的訊息中介軟體,開源專案地址:http://github.com/robey/kestrelComet Server:Comet是一種ajax長連線技術,利用Comet可以實現伺服器主動向web瀏覽器推送資料,從而避免客戶端的輪詢帶來的效能損失。libmemcached:一個memcached客戶端使用mysql資料庫伺服器Mongrel:Ruby的http伺服器,專門應用於rails,開源專案地址:http://rubyforge.org/projects/mongrel/Munin:服務端監控程式,專案地址:http://munin-monitoring.org/Nagios:網路監控系統,專案地址:http://www.nagios.org/三、快取講著講著就又說到快取了,確實,快取在大型web專案中起到了舉足輕重的作用,畢竟資料越靠近CPU存取速度越快。下圖是twitter的快取架構圖:twitter的快取架構圖大量使用memcached作快取例如,如果獲得一個count非常慢,你可以將count在1毫秒內扔入memcached獲取朋友的狀態是很複雜的,這有安全等其他問題,所以朋友的狀態更新後扔在快取裡而不是做一個查詢。不會接觸到資料庫 ActiveRecord物件很大所以沒有被快取。Twitter將critical的屬性儲存在一個雜湊裡並且當訪問時遲載入 90%的請求為API請求。所以在前端不做任何page和fragment快取。頁面非常時間敏感所以效率不高,但Twitter快取了API請求在memcached快取策略中,又有所改進,如下所述:1、建立一個直寫式向量快取Vector Cache,包含了一個tweet ID的陣列,tweet ID是序列化的64位整數,命中率是99%2、加入一個直寫式行快取Row Cache,它包含了資料庫記錄:使用者和tweets。這一快取有著95%的命中率。3、引入了一個直讀式的碎片快取Fragmeng Cache,它包含了通過API客戶端訪問到的sweets序列化版本,這些sweets可以被打包成json、xml或者Atom格式,同樣也有著95%的命中率。4、為頁面快取建立一個單獨的快取池Page Cache。該頁面快取池使用了一個分代的鍵模式,而不是直接的實效。四、訊息佇列大量使用訊息。生產者生產訊息並放入佇列,然後分發給消費者。Twitter主要的功能是作為不同形式(SMS,Web,IM等等)之間的訊息橋使用DRb,這意味著分散式Ruby。有一個庫允許你通過TCP/IP從遠端Ruby物件傳送和接收訊息,但是它有點脆弱 移到Rinda,它是使用tuplespace模型的一個分享佇列,但是佇列是持久的,當失敗時訊息會丟失 嘗試了Erlang 移到Starling,用Ruby寫的一個分散式佇列 分散式佇列通過將它們寫入硬碟用來挽救系統崩潰。其他大型網站也使用這種簡單的方式五、總結1、資料庫一定要進行合理索引2、要儘可能快的認知你的系統,這就要你能靈活地運用各種工具了3、快取,快取,還是快取,快取一切可以快取的,讓你的應用飛起來。

JustinTV網站架構

Justin.TV每月有3000萬個獨立訪問量,在遊戲視訊上傳領域打敗了YouTube ,他們每天每分鐘新增30個小時的視訊,而YouTube只有23。

下面從Justin.TV的實時視訊系統使用到的平臺,他們的架構細節,從他們身上應該學到的東西等幾個方面逐一展開。

使用到的平臺

  • Twice —— 代理服務系統,主要用緩衝優化應用伺服器負載
  • XFS —— 檔案系統
  • HAProxy —— 用於TCP/HTTP負載平衡
  • LVS stack and Idirectord —— 高可靠性
  • Ruby on Rails —— 應用伺服器系統
  • Nginx —— web伺服器系統
  • PostgreSQL —— 資料庫,用於使用者和meta資料
  • MongoDB —— 資料庫,用於內部分析
  • MemcachedDB —— 資料庫,用於存放經常要修改的資料
  • Syslog-ng —— 日誌服務系統
  • RabitMQ  —— job系統
  • Puppet —— 建立服務
  • Git —— 原始碼管理
  • Wowza —— Flash/H.264視訊伺服器和許多Java寫的custome modules
  • Usher —— 播放視訊流的邏輯控制伺服器
  • S3 —— 用於儲存小型映象

Justin.TV的一些統計資料

  • 有覆蓋全美的4個數據中心
  • 在任何時候都有2000多個同時流入的資料流
  • 每天每分鐘新增30個小時的視訊
  • 每月有3000萬個獨立訪問量(不計同一使用者多次訪問)
  • 每秒實時的網路流量在45G左右

實時視訊結構詳述

實時視訊結構

1.使用了P2P和CDN

一般人認為,只需要不斷提高頻寬,把傳來的資料都放入記憶體,不斷的接收資料流就可以了,事實並非如此。實時視訊要求不能打斷,這就意味著你不可以超負荷的使用頻寬。YouTube只需要讓播放器緩衝一下,就可以用8G的頻寬解決10G通道的需求,但在實時視訊裡,你不能緩衝,如果在通道上的流量超過了它的傳輸能力,哪怕只是一瞬間,那麼所有的正在看的使用者在那一刻都會卡。如果你在它的極限能力上再加入了一點兒負載,所有人立刻就會進入緩衝狀態。

Justin.TV使用了點對點的結構來解決這個問題,當然他們也有更好的解決辦法,CDN(內容分發網路)便是之一。當用戶的流量負載超過Justin.TV的負載能力時,Justin.TV便很巧妙的將超標流量引入到一個CDN中去,Usher控制著這個處理邏輯,一旦接到了超標使用者的負載請求,Usher便立刻將這些新使用者轉發到CDN中去。

2.100%可用時間和維護的矛盾

實時視訊構建的系統既要保證100%的可用時間,又要保證機器可以進行維護。與一般網站不同,一般網站維護時出現的問題只有少數人會發現、關注,而實時視訊網站不同,使用者很快就會發現維護時帶來的任何問題,並且互相傳播的非常快。這就使得沒有什麼問題可以隱瞞使用者,面對現在使用者的挑剔,你必須避免維護時出問題。對一個伺服器維護時,你不能主動結束使用者的程序,必須等待所有在這個伺服器上的使用者自己結束服務才能開始,而這個過程往往非常緩慢。

3.Usher與負載均衡

Justin.TV遇到的最大的麻煩是即時擁塞,當大量的使用者同時看同一個欄目的時候,便會突然產生突發網路擁塞。他們開發了一個實時的伺服器和資料中心排程系統,它就是Usher。

Justin.TV的系統在突發的高峰擁塞上做了很多。他們的網路每秒可以處理大量的鏈入連線。使用者也參與了負載均衡,這也是Justin.TV需要使用者使用Justin.TV自己的播放器的原因之一。至於TCP,由於它的典型處理速度就是百kbps級的,所以也不用對TCP協議做什麼修改。

相對於他們的流量,他們的視訊伺服器看來來有些少,原因是他們可以使用Usher把每個視訊伺服器的效能發揮到最好,負載均衡可以確保流量從不會超過他們的負載極限。負載大部分是在記憶體中,因此這個系統可以讓網路的速度發揮到極限。伺服器他們是一次從Rackable(SGI伺服器的一個系列)買了一整套,他們做的僅僅是從所有預置的裡面做了下挑選。

Usher是Justin.TV開發的一款定製化軟體,用來管理負載平衡,使用者認證和其他一些流播放的處理邏輯。Usher通過計算出每個流需要多少臺伺服器提供支援,從而分配資源,保證系統處於最優狀態,這是他們的系統和別家不同之處。Usher通常會從下面幾個指標計算、衡量某個流媒體所需要的伺服器:

  • 每個資料中心的負載是多少
  • 每個伺服器的負載是多少
  • 延遲優化的角度
  • 當前這個流可用的伺服器列表
  • 使用者的國家(通過IP地址獲得)
  • 使用者是否有可用的對等網(通過在路由資料庫中查詢IP地址獲得)
  • 請求來自於哪個資料中心

Usher使用這些指標便可以在服務淨成本上來優化,把服務放在比較空閒的伺服器上,或者把服務放在離使用者較近的伺服器上,從而給使用者帶來更低的延遲和更好的表現。Usher有很多個可以選擇的模式從而達到很細的控制粒度。

Justin.TV系統的每個伺服器都可以做邊緣伺服器,直接為使用者輸出視訊流,同時每個伺服器也可以做源伺服器,為其他伺服器傳遞視訊流。這個特性,使得視訊流的負載結構成了動態的,經常改變的一個過程。

4.伺服器形成了加權樹

伺服器之間由視訊流的拷貝而產生的聯絡和加權樹非常相似。資料流的數量經常被系統取樣、統計,如果觀看某個視訊流的使用者數量飛速上漲,系統便將其拷貝很多份到一些其他的伺服器上去。這個過程反覆執行,最終就形成了一個樹狀的結構,最終會將網路中所有的伺服器都畫在裡面。Justin.TV的視訊流從源伺服器出發,被拷貝到其他伺服器,或者拷貝到使用者的整個過程中,都處於記憶體中,沒有硬碟路徑的概念。

5.RTMP和HTTP

Justin.TV儘可能的使用了Flash,因為它使用RTMP協議,對每個視訊流,系統都有一個獨立的Session去維護它。由於使用這個協議,成本就相當高。由於ISP不支援下載流,因而無法使用多路廣播和P2P技術。Justin.TV確實想過用多路廣播在內部伺服器之間拷貝資料流,然而由於他們的系統控制覆蓋整個網路,而且內部有大量的很便宜的頻寬可以使用,這樣使用多路廣播的技術就並沒有產生多少效益。同時,由於他們的優化演算法是將每個伺服器上的流數都最小化,這就使得在很細的力度上做些事情會非常麻煩,甚至超過了他們能得到收益。

Justin.TV的Usher使用HTTP請求去控制某個伺服器負載哪個視訊流,從而控制了服務的拓撲結構。Justin.TV在流資料上使用HTTP,但存在的一個問題是它沒有延遲和實時方面的效能。有些人說實時的定義就是5-30秒,然而,面對數千人做實時視訊的時候這顯然不行,因為他們還需要實時的討論,交流,這意味著延遲不能高於1/4秒。

6.從AWS到自己的資料中心

起初Justin.TV使用AWS,後來遷移到Akamai(雲服務供應商),最後到了自己的資料中心。

離開AWS到Akamai的原因有:1,成本;2,網速不能滿足他們的需求。視訊直播對頻寬非常敏感,因此有一個快速的,可靠的,穩定的和低延遲的網路非常關鍵。使用AWS時,你不能控制這些,它是一個共享的網路,常常超負載,AWS的網速不會比300Mbps更快。他們對動態範圍改動和雲API很重視,然而在效能和成本問題上沒有做什麼。

3年前,Justin.TV計算他們每個使用者的成本,CDN是$0.135,AWS是0.0074,Datacenter是$0.001如今,他們的CDN成本降低了,但他們的資料中心的成本卻仍然一樣。

擁有多個數據中心的關鍵是為了能夠接近所有的主要交換節點,他們選擇國內最好的位置從而使得他們為國內最多的節點提供了入口,而且節約了成本,構建了這些資料中心後,他們就直接連入了這些其他的網路,從而就省去了之前處理這些中轉流量的費用,還提高了效能,他們直接連入了他們所謂的"eyeball"網路,這個網路中包含了大量的cable/DSL使用者,和"content"網路連線有些類似,Justin.TV的"eyeball"連線的流量主要來自終端使用者,在大多數情況下,這些都是免費的,不用任何花一分錢,要做的就是連進來就行。Justin.TV有一個主幹網,用於在不同的資料中心傳輸視訊流,因為要到一個可用節點的選拔過程是去找願意和你做對等節點的過程,這通常是很困難的。

7.儲存

視訊流不是從磁碟形成,而是要存到磁碟上去。源伺服器將一個傳入的視訊流在本地磁碟上覆制一份,之後便將這個檔案上傳到長期儲存器上,視訊的每一秒都被錄下來並且存檔了。

儲存裝置和YouTube類似,就是一個磁碟庫,使用XFS檔案系統。這個結構用於記錄通過伺服器傳播的廣播。預設的視訊流是儲存7天,使用者可以手動的設定,甚至你可以儲存到永遠(如果公司沒有倒閉的話)。

8.實時轉碼

增加了實時的轉碼功能,可以將任何一種流式資料轉化為傳輸層資料或者是程式碼,並且可以用新的格式將它重新編為流媒體。有一個轉碼叢集,用來處理轉換工作轉,換的會話使用job系統進行管理。如果需要的轉碼服務超過了叢集的處理能力,那所有的伺服器都可以用作轉碼伺服器。

Web結構

Web 結構

1.Justin.TV前端使用Ruby on Rails。

2.用Twice做快取

系統個每個頁面都使用了他們自己定製的Twice快取系統,Twice扮演的角色是輕量級反向代理伺服器和模板系統的合併角色。思路是對每一個使用者,快取每一個頁面,然後將每個頁面的更新再併入其中。使用Twice以後,每個程序每秒可以處理150條請求,同時可以在後臺處理10-20個請求,這就擴充套件了7-10倍之前的伺服器可以處理的網頁的數量。大部分動態網頁訪問都在5ms以內。Twice有一個外掛結構,所以它可以支援應用程式的一個特點,例如新增地理資訊。

不用觸及應用伺服器,便能自動快取像使用者名稱一樣的資料。

Twice是一個為Justin.TV的需求和環境而定製化開發的。如果開發一個新的Rails應用,使用Varnish或許是一個更好的主意。

3.網路流量由一個數據中心服務,其他的資料中心為視訊服務。

4.Justin.TV 對所有的操作都做了監控.每一個點選,檢視頁面和每一個動作都被記錄下來,這樣就可以不斷提高服務。前端,網路呼叫或者一個應用伺服器的日誌訊息都被轉換成系統日誌訊息,通過syslog-ngto轉發。他們掃描所有的資料,將它裝入MongoDB,使用Mongo執行查詢。

5.Justin.TV的API來自網站的應用伺服器,它使用相同緩衝引擎,通過擴充套件網站來擴充套件他們的API。

6.PostegreSQL是他們最主要的資料庫。結構是簡單的主從結構,由一個主機和多個從屬讀資料庫組成。

由於他們網站的型別,他們不需要許多寫資料庫,緩衝系統控制著這些讀資料庫。他們發現PostgreSQL並不擅長處理寫操作,因此Justin.TV就是用MemcachedDB去處理那些經常要寫的資料,例如計數器。

7.他們有一個聊天伺服器叢集,專門用來為聊天功能服務。如果使用者進入了一個頻道,使用者就會有5個不同的聊天伺服器為他服務,擴充套件聊天功能要比擴充套件視訊功能簡單的多,使用者可以被劃分到不同的房間,這些房間又由不同的伺服器負載。他們也不會讓100,000個人同時在一起聊天。他們限制每個房間200人,這樣就可以在一個小組裡進行更有意義的交談。這同時對擴充套件也很有幫助,這真的是一個很聰明的策略。

8.AWS用於儲存文件映象。他們沒有為儲存許多小映象而開發專門的系統,他們使用了S3。它非常方便,而且很便宜,這就不用在他們上面花更多的時間了。他們的映象使用頻率很高,所有他們是可緩衝的,也沒有留下什麼後續問題。

網路拓撲結構設計

網路拓撲結構非常簡單,每個伺服器機架頂都有一對1G的卡,每個機架都有多個10G的介面,介面連線到外部的核心路由器。他們使用Dell Power Edge交換機,這些交換機對L3(TCP/IP)並不是完全支援,但是比L2(ethernet)要好的多。每個交換機每天要傳輸20G的資料,而且很便宜。核心路由器是思科的6500的系列。Justin.TV想要將節點最小化,從而讓延遲降低,並且降低每個packet的處理時間。Usher管理著所有的接入控制和其他的邏輯,而不僅僅限於網路硬體。

使用多個數據中心可以充分利用對等網的優勢,把流量轉移到離使用者最近的地方。和其他的網路和節點的連線非常多。這樣就有多個可選的傳輸途徑,所以可以使用最好的那個路徑。如果他們遇到了網路的擁塞,就可以選擇一條別的路。他們可以通過IP地址和時間,找到對應的ISP。

開發和部署

他們使用Puppet伺服器主機,有20中不同種類的伺服器。從資料庫中出來的任何東西都要經過快取器,使用Puppet他們可以把這個快取器變成他們想要的任何東西。

他們有兩個軟體隊伍。一個是產品隊伍,另一個是硬體基礎設施隊伍。他們的隊伍非常小,大概每個隊伍只有7-8個人,每個隊伍都有一個產品經理。他們僱傭一般的技術員,但卻僱傭了網路結構和資料庫相關的專家。

他們使用了基於網路的開發系統,所以每個新的改動都會在幾分鐘內完成。QA必須在變成產品之前完成,在這裡通常需要5-10分鐘。

Justin.TV使用Git管理原始碼。Justin.TV喜歡Git的這個功能,你可以寫一個程式副本,20-30行,然後它可以融合到其他人手裡正在修改的副本。這個工作是獨立的,模組化的。在你不得不撤銷你提交的副本時,你可以很容易就修改或者撤銷你的程式碼。每過幾天每個人都會試著將自己的程式碼副本融入到主程式碼中去消除衝突。他們每天對軟體做5-15個修改,範圍從1行程式碼中的bug到大範圍的測試都有。

資料庫模式通過手動更新完成。將他們複製的資料庫副本遷移到一起就會形成一個最新的動態記錄的版本。在把改動最終應用到產品之前會在許多不同的環境下對其進行測試。

Puppet管理配置檔案。每個小的改動基本上就是一個實驗,他們會追蹤每個對核心檔案的改動的影響和之前的版本。這些測試很重要,因為通過它他們可以找出哪些改動是真正提高他們關心的指標。

Justin.TV的未來

他們的目標是增加一個數量級。首先要切分他們的視訊元資料系統,由於流資料和伺服器的大幅增長,他們的元資料負載也指數級的爆發增長,因此,他們需要將其大範圍進行切分,對於網路資料庫,將使用Cassandra對其進行拆分。其次,為了災後恢復,要對核心資料中心進行備份。

學到的東西

  • 自己開發還是購買。他們在這個問題上已經做了很多錯誤的決策。例如,他們起初應該買一臺視訊伺服器而不是自己去做了一臺。軟體工程師喜歡將軟體做的個性化,然後使用開源社群維護的東西卻有很多益處。因此他們提出了一個更好的流程去做這個決定:1.這個專案是活動?還是維護?還是修補漏洞?2.有其他的人要用它麼?你能向別人請教下該如何定義它?3.擴充套件性的問題,他們必須去做改變。4.如果我們自己開發,我們可以做到更快,更好,還是我們可以獲得更多我們需要的特性呢? 就像使用Usher,他們考慮他們可否創造一個新的外部特性,並且和另外一個系統互動。把Usher做為視訊擴充套件性的核心針對相對笨拙的視訊伺服器來說是一個非常好的決策的例子。
  • 關注自己做的事情,不要在意別人怎麼幹。他們的目標是有用最好的系統,最多的服務時間和最完美的擴充套件性。他們用了3年去開發能管理百萬個廣播併發的技術。
  • 不要外包。你學到的核心價值在於經驗,而不是程式碼或者硬體。
  • 把一切都當做實驗來做。對所有的東西都進行測量,區域性測試,追蹤,測量。這很划算。從一開始就做,使用優秀的測量工具。例如,他們在複製的URL上附加一個標籤,然後就可以知道你是否分享了這個連結。他們從不測量的走到了如今高度測量。通過重寫廣播程序,使得他們的會話數量增長了700%。他們想要網站執行更快,響應更快,網頁裝載更快,視訊服務更好,系統擠出的每一毫秒的延遲都帶來了更多的廣播者。他們有40個實驗,如果他們希望讓一個使用者變成一個廣播者,對每個實驗他們都想要看一下廣播後的留存率,廣播的可用性,會話率,然後對每個改動都做一個明智的決策。
  • 最重要的一件事是理解你的網站如何共享服務,怎麼優化它。他們通過減少共享的連結在選單中的深度,成功的提高了500%的分享率。
  • 使用公共的構建模組和基礎設施意味著系統將立刻識別什麼是重要的,然後執行。具有網路能力很重要,這也是他們應該從開始就關注的地方。
  • 讓系統忙起來。使用系統的所有能力,為什麼要把錢放在桌子上呢?構建可以通過應答對系統進行合理的分配的系統。
  • 對不重要的事情不要浪費時間。如果它非常方便並且不用花費多少,就沒有必要在它上面花費時間。使用S3去儲存映象就是一個很典型的例子。
  • 試著為使用者想做的事情提供支援,而不是做你認為使用者該這樣使用的東西。Justin.TV的終極目標似乎是把所有人都變成一個廣播點。在使用者實驗時,通過儘可能的走出使用者的使用方式,他們試著讓這個過程變得儘可能簡單。在這過程中,他們發現,遊戲是一個巨大的作用力。使用者喜歡將Xbox截圖出來,並且與大家分享,討論它,很有可能有些東西是你沒想過要放在商務計劃裡的。
  • 為負載峰值做設計。如果你只為了靜態的狀態做了設計,之後你的網站將會在峰值來臨時垮掉。在實時視訊上,這通常是一個大事,如果你陷入了這個麻煩,很快人們就開始傳播對你不利的話。為峰值負載進行設計需要使用一個所有層次的技術。
  • 讓網路結構保持簡單。使用多資料中心,使用點對點網路連線結構。
  • 不要擔心將東西劃分到更多的可擴充套件塊中去。例如,與其使用一個100,000人的頻道,不如將他們劃分到更多的社會和可擴充套件的頻道去。
  • 實時系統不能隱藏來自使用者的任何問題,這就是的說服使用者你的網站很可靠變的很困難。由於他們和實時系統之間的聯絡是固定的,這會使的系統的每個問題和故障都讓大家知道,你藏不住。每個人都會發現,並且每個人都會通過交流傳播發生了什麼,很快,使用者就會有一個你的網站有很多問題的感覺。在這種情況下,和你的使用者交流就變得很重要,從一開始就構建一個可信賴的,高質量的,可擴充套件的,高效能的系統,設計一個使用者用起來儘可能簡單和舒服的系統。(編譯:@康文博/審校:仲浩)
摘自:http://www.csdn.net/article/2012-11-23/2812183-JustinTV_real-time_architecture