Netflix是一家在線影片租賃提供商,該公司連續(xù)五次被評(píng)為顧客最滿意的網(wǎng)站,在過(guò)去的7年中,Netflix流媒體服務(wù)從偶爾有數(shù)千用戶在線觀看發(fā)展到了數(shù)百萬(wàn)用戶平均每月觀看超過(guò)20億個(gè)小時(shí)的規(guī)模。Netflix之所以能夠如此成功,離不開(kāi)對(duì)用戶行為數(shù)據(jù)的收集與分析,那么Netflix會(huì)收集哪些數(shù)據(jù),這些數(shù)據(jù)會(huì)用來(lái)做什么,其處理架構(gòu)又是什么呢?
事實(shí)上,當(dāng)用戶開(kāi)始在Netflix的網(wǎng)站上觀看電影或者電視節(jié)目的時(shí)候,Netflix的數(shù)據(jù)系統(tǒng)會(huì)創(chuàng)建一個(gè)“觀看會(huì)話(view)”,描述該會(huì)話的所有事件信息都會(huì)被收集起來(lái)。該觀看會(huì)話數(shù)據(jù)架構(gòu)能夠應(yīng)對(duì)從用戶體驗(yàn)到數(shù)據(jù)分析的諸多場(chǎng)景,其中最主要的場(chǎng)景有三個(gè):
用戶看了哪些視頻?系統(tǒng)需要知道每一個(gè)用戶的所有觀看歷史,以便于為用戶推薦相關(guān)的視頻內(nèi)容,同時(shí)在頁(yè)面上的“最近觀看”一欄中顯示觀看歷史。用戶所看的內(nèi)容對(duì)于用戶興趣的衡量,產(chǎn)品和內(nèi)容的決定非常重要。
用戶從哪里離開(kāi)了視頻?對(duì)于每一個(gè)電影或者電視節(jié)目,Netflix會(huì)記錄每一個(gè)用戶都看到了哪里,從哪個(gè)時(shí)間點(diǎn)離開(kāi)的。這使得Netflix的用戶能夠在同一個(gè)或者另一個(gè)設(shè)備上繼續(xù)觀看視頻。
當(dāng)前帳戶現(xiàn)在還在觀看哪些視頻?家庭成員間的帳戶共享使得任何人可以在任何時(shí)候觀看自己喜歡的視頻,但是這也意味著當(dāng)帳戶同時(shí)在線數(shù)超限的時(shí)候,必須要有人放棄觀看。針對(duì)這種場(chǎng)景,Netflix的觀看會(huì)話數(shù)據(jù)系統(tǒng)會(huì)收集每一個(gè)會(huì)話的周期性信號(hào)以便于決定某個(gè)成員是否還在觀看相關(guān)視頻。
這些場(chǎng)景的實(shí)現(xiàn)離不開(kāi)強(qiáng)大而穩(wěn)定的數(shù)據(jù)處理系統(tǒng),Netflix目前的系統(tǒng)架構(gòu)由早期的單數(shù)據(jù)庫(kù)應(yīng)用程序演變而來(lái),當(dāng)時(shí)的主要需求是能夠低延遲地為用戶提供視頻服務(wù),同時(shí)還能夠處理來(lái)自于數(shù)百萬(wàn)Netflix流設(shè)備的快速增長(zhǎng)的數(shù)據(jù)集。在過(guò)去3年多的時(shí)間里,Netflix一直在不斷地改進(jìn)該架構(gòu),現(xiàn)在這套系統(tǒng)每天能夠處理千億左右的事件。
當(dāng)前的架構(gòu)圖如下:
整個(gè)架構(gòu)最主要的接口是觀看會(huì)話服務(wù),它分為有狀態(tài)層和無(wú)狀態(tài)層兩部分。有狀態(tài)層在內(nèi)存中存有所有活動(dòng)視圖的最新數(shù)據(jù)。通過(guò)對(duì)用戶帳戶ID進(jìn)行mod N的模運(yùn)算,數(shù)據(jù)被簡(jiǎn)單地劃分為N個(gè)有狀態(tài)的節(jié)點(diǎn)。當(dāng)有狀態(tài)的節(jié)點(diǎn)上線的時(shí)候,系統(tǒng)會(huì)通過(guò)一個(gè)位置選擇流程決定哪部分?jǐn)?shù)據(jù)屬于它們。所有的持久化數(shù)據(jù)都存儲(chǔ)在Cassandra中,在Cassandra之上有一個(gè)Memcached用來(lái)保證低延遲的讀取路徑,但是采用這種方式會(huì)話數(shù)據(jù)有可能會(huì)過(guò)時(shí),同時(shí)如果一個(gè)有狀態(tài)的節(jié)點(diǎn)出現(xiàn)了錯(cuò)誤,那么1/n的瀏覽數(shù)據(jù)將不能讀寫(xiě)。無(wú)狀態(tài)層的引入正是為了解決這一問(wèn)題,它提升了系統(tǒng)的可用性,當(dāng)有狀態(tài)的節(jié)點(diǎn)無(wú)法訪問(wèn)的時(shí)候,該層會(huì)將過(guò)時(shí)的數(shù)據(jù)反饋給用戶。
但是即使是做了諸多改進(jìn),以上架構(gòu)依然存在一些缺陷:
雖然有狀態(tài)層使用一個(gè)簡(jiǎn)單的、服從熱點(diǎn)分布的分片技術(shù),但是Cassandra層并不服從這些熱點(diǎn);同時(shí),如果將其從一個(gè)AWS Region移動(dòng)到多個(gè)AWS Region上運(yùn)行,那么必須定制一種機(jī)制來(lái)實(shí)現(xiàn)分布在不同Region上的狀態(tài)層之間的狀態(tài)通信,極大地增加了系統(tǒng)的復(fù)雜性。
對(duì)于觀看會(huì)話服務(wù),它封裝了會(huì)話數(shù)據(jù)的收集、處理和提供功能,隨著系統(tǒng)的演變,功能的增多,該服務(wù)的責(zé)任也越來(lái)越多,增加了運(yùn)維的難度。
雖然Memcached提供了非常好的吞吐量和延遲特性,但是使用一種能夠?yàn)橐坏葦?shù)據(jù)類型和操作(例如append)提供原生支持的技術(shù)能夠更好地滿足相關(guān)需求。
為了擴(kuò)展系統(tǒng)滿足下一個(gè)數(shù)量級(jí)的需要,Netflix正在重新思考自己的基礎(chǔ)架構(gòu),新系統(tǒng)在設(shè)計(jì)時(shí)考慮的主要設(shè)計(jì)原則包括:
可用性比一致性更重要。
微服務(wù)。對(duì)于有狀態(tài)架構(gòu)中柔和在一起的組件,根據(jù)它們的主要目的分離成單獨(dú)的服務(wù)——或收集、處理或提供數(shù)據(jù)。將狀態(tài)管理功能托管到持久化層,讓?xiě)?yīng)用程序?qū)訜o(wú)狀態(tài),同時(shí)組件之間通過(guò)事件隊(duì)列解耦。
混合持久化。使用多種持久化技術(shù),利用每一種方案的優(yōu)勢(shì)。使用Cassandra實(shí)現(xiàn)高容量、低延遲的寫(xiě)。使用Redis實(shí)現(xiàn)高容量、低延遲的讀。
遵循以上原則的新架構(gòu)實(shí)現(xiàn)如下:
當(dāng)然,這個(gè)架構(gòu)圖也僅僅是Netflix目前的設(shè)計(jì)圖,至于實(shí)現(xiàn)到何種程度了,我們還未可知。Netflix表示對(duì)關(guān)鍵系統(tǒng)進(jìn)行重新架構(gòu)以使其能夠擴(kuò)展到下一個(gè)數(shù)量級(jí)是一項(xiàng)非常困難的工作,需要長(zhǎng)時(shí)間的開(kāi)發(fā)、測(cè)試和驗(yàn)證,同時(shí)遷移也不是那么容易。但是以這些架構(gòu)原則為指導(dǎo),Netflix相信他們正在構(gòu)建的下一代系統(tǒng)能夠滿足自己大規(guī)模、快速增長(zhǎng)的需要。