【導(dǎo)語(yǔ)】:作者在上一篇文章《基于內(nèi)容的推薦算法》中介紹了基于內(nèi)容的推薦算法的實(shí)現(xiàn)原理。在本篇文章中作者會(huì)介紹一個(gè)具體的基于內(nèi)容的推薦算法的實(shí)現(xiàn)案例。該案例是作者在2015年基于Erlang語(yǔ)言開(kāi)發(fā)的相似視頻推薦系統(tǒng),從開(kāi)發(fā)完成就一直在公司多個(gè)產(chǎn)品線中使用,該算法目前已經(jīng)使用了四年。
本文會(huì)從視頻相似推薦系統(tǒng)簡(jiǎn)介、算法原理及實(shí)現(xiàn)細(xì)節(jié)、問(wèn)題與難點(diǎn)、為什么用Erlang語(yǔ)言開(kāi)發(fā)、系統(tǒng)架構(gòu)與工程實(shí)現(xiàn)、核心亮點(diǎn)、未來(lái)優(yōu)化方向、個(gè)人收獲與感悟等8個(gè)方面來(lái)講解。
通過(guò)學(xué)習(xí)本文讀者可以深入了解基于向量空間模型的相似推薦算法原理及實(shí)現(xiàn)細(xì)節(jié)、對(duì)Erlang語(yǔ)言特性也會(huì)有基本的了解、同時(shí)對(duì)實(shí)現(xiàn)一個(gè)簡(jiǎn)單高效的Master/Slaver架構(gòu)的分布式計(jì)算框架的原理和工程細(xì)節(jié)有基本的概念。
視頻相似推薦系統(tǒng)簡(jiǎn)介
作者所在公司從事智能電視/智能機(jī)頂盒上的視頻業(yè)務(wù)(主要產(chǎn)品是電視貓),由于智能電視上主要依賴(lài)遙控器操作,所以操控不是很方便,產(chǎn)品對(duì)推薦系統(tǒng)的依賴(lài)會(huì)更大。而相似推薦就是為每個(gè)視頻關(guān)聯(lián)一組相似(或者有一定關(guān)聯(lián)關(guān)系)的視頻。
具體產(chǎn)品形態(tài)見(jiàn)下圖1和圖2:
圖1:電視貓電影詳情頁(yè)的相似影片
圖2:電視貓奇趣短視頻的關(guān)聯(lián)推薦
我們的產(chǎn)品包括長(zhǎng)視頻(電影、電視劇、動(dòng)漫、少兒、紀(jì)錄片、綜藝6種)和短視頻(資訊、奇趣、游戲、體育、戲曲、音樂(lè)6種)兩大類(lèi),我們需要為每類(lèi)視頻類(lèi)型的節(jié)目關(guān)聯(lián)一組相似推薦(在同一類(lèi)別中做推薦,電影的相關(guān)推薦只能是電影、體育的關(guān)聯(lián)推薦是體育等)。
具體怎么計(jì)算相似呢?我們是基于視頻的metadata信息來(lái)計(jì)算兩個(gè)視頻之間的相似度,利用相似度從高到低來(lái)排序,獲取某個(gè)視頻最相似的topN作為關(guān)聯(lián)或者相似推薦。
這里提一下,雖然長(zhǎng)視頻和短視頻采用同一套算法體系,但是由于視頻類(lèi)型不一樣,前端的產(chǎn)品形態(tài)是不一樣的。由于短視頻單片時(shí)長(zhǎng)較短,一般幾分鐘就播完了,所以短視頻的關(guān)聯(lián)推薦采用的是信息流的方式,播放原視頻,它關(guān)聯(lián)的視頻會(huì)作為信息流播放,這樣整體用戶(hù)體驗(yàn)會(huì)好很多(這就是上面圖1和圖2雖然都是相似推薦但是產(chǎn)品形態(tài)不一樣的原因)。
相信通過(guò)上面的介紹,大家對(duì)視頻相似推薦的產(chǎn)品形態(tài)比較清楚了。在下面一節(jié),我們來(lái)講解具體的算法實(shí)現(xiàn)細(xì)節(jié)。
算法原理及具體實(shí)現(xiàn)細(xì)節(jié)
視頻行業(yè)一般是具備結(jié)構(gòu)化信息的,一般視頻公司會(huì)有CMS(Content Management System,內(nèi)容管理系統(tǒng)),該系統(tǒng)一般會(huì)包含媒資庫(kù),媒資庫(kù)中針對(duì)每個(gè)節(jié)目會(huì)有標(biāo)題、演職員、導(dǎo)演、標(biāo)簽、評(píng)分、地域等維度數(shù)據(jù),這類(lèi)數(shù)據(jù)一般存放在關(guān)系型數(shù)據(jù)庫(kù)(如MySQL)中。
這類(lèi)數(shù)據(jù),我們可以將一個(gè)字段(也是一個(gè)特征)作為向量的一個(gè)維度,這時(shí)用向量表示視頻,每個(gè)維度的值不一定是數(shù)值,但是形式還是向量化的形式,即所謂的向量空間模型(Vector Space Model,簡(jiǎn)稱(chēng)VSM)。這時(shí)我們可以通過(guò)如下的方式計(jì)算兩個(gè)視頻之間的相似度。
假設(shè)兩個(gè)視頻的向量表示分別為:
?? ??
?? ? ?
這時(shí)這兩個(gè)視頻的相似度可以采用如下公式計(jì)算:
其中代表的是向量的兩個(gè)分量?之間的相似度。可以采用Jacard相似度等各種方法計(jì)算兩個(gè)分量之間的相似度。上面公式中還可以針對(duì)不同的分量采用不同的權(quán)重策略,見(jiàn)下面公式,其中?是第t個(gè)分量(特征)的權(quán)重,具體權(quán)重的數(shù)值可以根據(jù)對(duì)業(yè)務(wù)的理解來(lái)人工設(shè)置,或者利用機(jī)器學(xué)習(xí)算法來(lái)訓(xùn)練學(xué)習(xí)得到。
有了上面的計(jì)算公式,我們就知道該怎么計(jì)算兩個(gè)視頻的相似度了。但是上面公式中未解決的問(wèn)題是,對(duì)于某一個(gè)具體的維度,我們?cè)撛趺从?jì)算相似度呢?
上式中的?、???分別代表兩個(gè)節(jié)目第 i 個(gè)維度的值,可以是數(shù)值、字符串等。下面我們列舉一下針對(duì)不同的分量怎么計(jì)算分量之間的相似度。
年代
假設(shè)兩個(gè)視頻???的年代分別是???和???,計(jì)算在年代這個(gè)維度的相似度可以采用如下分段函數(shù)表示:
其中(1)、(2)是剔除掉無(wú)效的??值,(3)是給出的當(dāng)???在0到2020年之間的一個(gè)計(jì)算公式,??值越大,最終的相似度越大。這里相似度與??無(wú)關(guān)(所以嚴(yán)格來(lái)說(shuō),不叫做相似度,而是貢獻(xiàn)度,下面類(lèi)似,不再說(shuō)明,直接用貢獻(xiàn)度來(lái)描述)在其他條件相同的情況下,越是近期拍攝的視頻權(quán)重越大。
標(biāo)題
假設(shè)兩個(gè)視頻?, ??和??分別是這兩個(gè)視頻的標(biāo)題,首先我們可以通過(guò)分詞或者關(guān)鍵詞提取算法將 ???和??提取關(guān)鍵詞得到對(duì)應(yīng)的關(guān)鍵詞,假設(shè)如下:
?? ? ?
?? ? ?
其中?分別是?提取關(guān)鍵詞后的集合,那么我們可以用如下Jacard相似度來(lái)計(jì)算??之間的相似度:
?? ? ?
這里涉及到很多NLP方面的技術(shù)和領(lǐng)域知識(shí)。首先我們需要有視頻行業(yè)相關(guān)語(yǔ)料,才能夠保證分詞準(zhǔn)確,另外標(biāo)題可能是雜亂無(wú)章的,比如很多電影標(biāo)題中包含粵語(yǔ)版、國(guó)語(yǔ)版、新傳、第三季等對(duì)相似度價(jià)值不大的詞或者詞組,這些都需要借助規(guī)則或者NLP技術(shù)做預(yù)處理,才能得到較好的關(guān)鍵詞提取效果,最終才會(huì)有較好的相似度計(jì)算效果。
標(biāo)簽
對(duì)于標(biāo)簽,可以采用跟上面標(biāo)題一樣的計(jì)算方法,因?yàn)闃?biāo)題提取關(guān)鍵詞后的每個(gè)關(guān)鍵詞可以看成是一個(gè)標(biāo)簽。這里不再細(xì)說(shuō)怎么計(jì)算了。
地域
假設(shè)兩個(gè)視頻??, ??和??分別是這兩個(gè)視頻的出品地,我們可以用如下公式來(lái)計(jì)算這兩個(gè)視頻在地域維度的相似度。
這個(gè)公式可以考慮得更復(fù)雜一點(diǎn),將地區(qū)按照語(yǔ)言、地域等分成幾類(lèi),比如北美、東歐、東南亞等,當(dāng)兩個(gè)視頻的地域完全一樣時(shí)相似度為1,當(dāng)兩個(gè)視頻在同一個(gè)地區(qū)分類(lèi)內(nèi),相似度為0.5(或者其他大于0小于1的值,根據(jù)業(yè)務(wù)經(jīng)驗(yàn)開(kāi)發(fā)人員自己定義),否則為0,這樣會(huì)更加精確合理。
豆瓣評(píng)分
假設(shè)兩個(gè)視頻?,??和??分別是這兩個(gè)視頻的豆瓣評(píng)分(豆瓣評(píng)分是0到10之間),下面公式給出視頻?? 在豆瓣評(píng)分這個(gè)維度的貢獻(xiàn)度,評(píng)分越高,貢獻(xiàn)度越大。
是否獲獎(jiǎng)
假設(shè)兩個(gè)視頻?,?? 和??分別是這兩個(gè)視頻所獲的獎(jiǎng)項(xiàng),那么可以簡(jiǎn)單用下面公式來(lái)計(jì)算視頻?? 在獲獎(jiǎng)這個(gè)維度上的貢獻(xiàn),當(dāng)然計(jì)算公式可以更加復(fù)雜,對(duì)不同獎(jiǎng)項(xiàng)區(qū)別對(duì)待,級(jí)別更高的獎(jiǎng)項(xiàng)可以給出更高的貢獻(xiàn)度。
導(dǎo)演與演員
通常情況下,視頻一般只有一個(gè)導(dǎo)演,導(dǎo)演的相似度可以類(lèi)似地域一樣的方法計(jì)算。而演職員可以采用跟標(biāo)簽類(lèi)似的方法計(jì)算相似度。
上面給出了幾個(gè)內(nèi)容維度怎么計(jì)算兩個(gè)視頻在該維度的相似度(或者貢獻(xiàn)度),我們?cè)趯?shí)際項(xiàng)目中用到的維度比這個(gè)更多,但是計(jì)算原理類(lèi)似,這里不再一一列舉。另外,具體的計(jì)算和處理邏輯也會(huì)更復(fù)雜,比如對(duì)于標(biāo)簽相似度,標(biāo)簽之間是有相似關(guān)系的,比如驚悚和恐怖,它們是相似的。上面方法沒(méi)有考慮到標(biāo)簽之間的這種相似關(guān)系而是將他們看成不同的標(biāo)簽,計(jì)算相似性多少有點(diǎn)簡(jiǎn)單。
實(shí)際上,我們項(xiàng)目中用到了數(shù)學(xué)中等價(jià)類(lèi)的思想,將很相似的標(biāo)簽看成是同一類(lèi)的,在同一類(lèi)的標(biāo)簽之間是有相似度的,這樣如果一個(gè)電影的標(biāo)簽是恐怖,另外一個(gè)電影的標(biāo)簽是驚悚,按照上面的計(jì)算方法相似度是0,而按照我們等價(jià)類(lèi)的思路,相似度是大于0的。同時(shí),對(duì)于某些類(lèi)別的視頻我們加了很多規(guī)則性的東西,更好地適應(yīng)不同類(lèi)別內(nèi)容的相似計(jì)算。像這類(lèi)提升效果的處理還有很多,這里不再細(xì)說(shuō)。
問(wèn)題與難點(diǎn)
該項(xiàng)目最早(2012年底)是采用Java來(lái)開(kāi)發(fā)的,寫(xiě)一個(gè)單機(jī)程序,當(dāng)時(shí)視頻量還比較少,也沒(méi)有這么多視頻類(lèi)別,基本可以支撐,當(dāng)后面加入越來(lái)越多的視頻類(lèi)別,每類(lèi)視頻數(shù)量也越來(lái)越多時(shí),單機(jī)計(jì)算的性能就出現(xiàn)瓶頸了。
當(dāng)時(shí)采用的應(yīng)對(duì)方案是將視頻按照類(lèi)別分成幾組,每一組采用一個(gè)Java線程計(jì)算,雖然某種程度上可以做到并行計(jì)算,但是每個(gè)視頻類(lèi)型的數(shù)量及增長(zhǎng)速度是不一樣的,人工按照類(lèi)型拆開(kāi)分布不夠均勻,問(wèn)題比較多。
回顧老的設(shè)計(jì)面臨的問(wèn)題,我們來(lái)總結(jié)一下,基于該算法的相似視頻推薦主要難點(diǎn)有如下幾個(gè):
數(shù)據(jù)量大,增速快
前面講到我們長(zhǎng)短視頻加起來(lái)大概有12個(gè)類(lèi)別,類(lèi)別多,總量有幾百萬(wàn)條視頻。對(duì)于短視頻來(lái)說(shuō),特別是資訊、體育等,每天都有大量(萬(wàn)級(jí))新增的節(jié)目。
第一次全量計(jì)算所有節(jié)目的相似度時(shí),由于需要計(jì)算的節(jié)目太多,必須采用分布式計(jì)算,否則計(jì)算太慢,單機(jī)可能要花幾個(gè)月時(shí)間才能完全算完。
需要實(shí)時(shí)計(jì)算
在我們的APP上,短視頻一般按照時(shí)間排列,新的短視頻放在最前面,用戶(hù)更容易看到。所以對(duì)于新增的視頻節(jié)目,我們需要實(shí)時(shí)計(jì)算出相似的視頻,否則只能用默認(rèn)推薦頂替相似推薦,效果肯定不會(huì)太好。
計(jì)算與某個(gè)視頻最相似的視頻需要遍歷所有視頻
我們一般只關(guān)聯(lián)推薦同一大類(lèi)的視頻,但是各個(gè)類(lèi)別數(shù)量是極不均衡的,電影1-2萬(wàn)部,資訊大概有上百萬(wàn)。在我們?yōu)槟硞€(gè)資訊計(jì)算與它最相似的N個(gè)資訊時(shí),我們需要遍歷所有其他的資訊才能找到與它最相似的N個(gè),怎么設(shè)計(jì)這個(gè)遍歷過(guò)程對(duì)計(jì)算時(shí)間有很大影響。
更新已經(jīng)計(jì)算的視頻的相似度
對(duì)于新入庫(kù)的視頻A,我們需要計(jì)算它的關(guān)聯(lián)推薦,同時(shí),對(duì)于某個(gè)已經(jīng)計(jì)算好的視頻B,如果新加入的視頻A與B的相似度高于B原來(lái)計(jì)算好的topN相似的某個(gè)視頻的相似度,這時(shí)需要更新B的相似度列表,將A添加進(jìn)去,同時(shí)刪除原來(lái)B的相似列表中相似度最低的視頻。每個(gè)新視頻的加入都可能影響很多已經(jīng)計(jì)算過(guò)相似度的視頻,怎么在短時(shí)間內(nèi)快捷地查找出這類(lèi)需要更新相似度列表的視頻也是一個(gè)挑戰(zhàn)。
上面我們對(duì)相似視頻推薦的算法原理及難點(diǎn)做了比較細(xì)致的講解。為了實(shí)現(xiàn)這些算法和克服難點(diǎn),我們基于Erlang語(yǔ)言完美地解決了這些問(wèn)題,在講怎么利用Erlang語(yǔ)言來(lái)從工程上實(shí)現(xiàn)上面的算法之前,我們先簡(jiǎn)單對(duì)Erlang語(yǔ)言做一個(gè)初略的介紹,方便讀者更好地理解后續(xù)算法的架構(gòu)和工程實(shí)現(xiàn)原理。
為什么要用Erlang語(yǔ)言開(kāi)發(fā)
Erlang語(yǔ)言簡(jiǎn)介
Erlang是一種通用的面向并發(fā)的編程語(yǔ)言,它由瑞典電信設(shè)備制造商愛(ài)立信所轄的CS-Lab開(kāi)發(fā),目的是創(chuàng)造一種可以應(yīng)對(duì)大規(guī)模并發(fā)事件的編程語(yǔ)言和運(yùn)行環(huán)境。Erlang問(wèn)世于1987年,經(jīng)過(guò)十年的發(fā)展,于1998年發(fā)布開(kāi)源版本。Erlang是運(yùn)行于虛擬機(jī)的解釋性語(yǔ)言。在編程范型上,Erlang屬于多重范型編程語(yǔ)言,涵蓋函數(shù)式、并發(fā)式及分布式。
Erlang是一個(gè)結(jié)構(gòu)化、動(dòng)態(tài)類(lèi)型編程語(yǔ)言,內(nèi)建并行計(jì)算支持。最初是由愛(ài)立信專(zhuān)門(mén)為通信應(yīng)用設(shè)計(jì)的,比如控制交換機(jī)或者變換協(xié)議等,因此非常適合于構(gòu)建分布式、實(shí)時(shí)并行計(jì)算系統(tǒng)。使用Erlang編寫(xiě)出的應(yīng)用程序運(yùn)行時(shí)通常由成千上萬(wàn)個(gè)輕量級(jí)進(jìn)程組成,并通過(guò)消息傳遞相互通訊。進(jìn)程間上下文切換對(duì)于Erlang來(lái)說(shuō)非常簡(jiǎn)單,比起C程序的線程切換要高效得多。
Erlang語(yǔ)言的特性
Erlang語(yǔ)言雖然開(kāi)發(fā)于上世紀(jì)80年代,但是很多思想是非常超前的,在當(dāng)前云計(jì)算時(shí)代具有非常實(shí)用的價(jià)值,算是在多如牛毛的編程語(yǔ)言大軍中獨(dú)樹(shù)一幟。這些特性也是我選擇利用Erlang語(yǔ)言開(kāi)發(fā)相似視頻推薦系統(tǒng)的主要原因之一。
下面我們列舉一些Erlang語(yǔ)言的主要特性:
(1) 函數(shù)式編程及部分語(yǔ)法特性
Erlang是一個(gè)函數(shù)式編程語(yǔ)言,即可以將函數(shù)作為參數(shù)傳入別的的函數(shù),并且可以作為函數(shù)的返回值。
Erlang語(yǔ)法也比較特殊,通過(guò)遞歸來(lái)實(shí)現(xiàn)迭代邏輯,沒(méi)有其他語(yǔ)言的while和for循環(huán)結(jié)構(gòu)。Erlang的變量跟數(shù)學(xué)中類(lèi)似,只能單次賦值,不可重復(fù)賦不同值。Erlang的模式匹配能力也非常強(qiáng)大。Erlang內(nèi)置了很多數(shù)據(jù)類(lèi)型及操作函數(shù),輔助更好地進(jìn)行函數(shù)式編程。
(2) 并發(fā)模型
Erlang是一個(gè)高并發(fā)語(yǔ)言,天生支持高并發(fā),Erlang基于Actor的并發(fā)編程模型,進(jìn)程間通信通過(guò)消息傳遞進(jìn)行,高效自然可靠。Erlang語(yǔ)言將并發(fā)模式作為自己的核心特性,非常方便構(gòu)建分布式處理邏輯,從一開(kāi)始設(shè)計(jì)之初就充分利用多核處理器性能,非常適合在現(xiàn)代服務(wù)器上構(gòu)建分布式應(yīng)用。
(3) 跨平臺(tái)
Erlang語(yǔ)言與java類(lèi)似,采用虛擬機(jī)來(lái)解釋執(zhí)行代碼,Erlang的beam虛擬機(jī)負(fù)責(zé)對(duì)代碼進(jìn)行解釋執(zhí)行,因此具備跨平臺(tái)特性,一次編譯到處運(yùn)行。
(3) 錯(cuò)誤處理
Erlang是一個(gè)高容錯(cuò)的編程框架,它對(duì)錯(cuò)誤處理有兩個(gè)設(shè)計(jì)哲學(xué):讓另外一個(gè)程序來(lái)解決錯(cuò)誤,如果出錯(cuò)就讓程序崩潰并重新啟動(dòng)。第一個(gè)設(shè)計(jì)哲學(xué)將錯(cuò)誤”外包“給另外一個(gè)專(zhuān)門(mén)的程序監(jiān)控和處理,這樣原來(lái)的程序?qū)⒑诵姆诺教幚磉壿嬌希@個(gè)監(jiān)控程序可以放在另外一臺(tái)機(jī)器上,如果原來(lái)程序所在機(jī)器掛了,監(jiān)控程序也可以發(fā)現(xiàn)問(wèn)題。
基于第二個(gè)設(shè)計(jì)哲學(xué),既然處理邏輯和處理錯(cuò)誤的程序分離了,如果處理邏輯的程序掛了(一般也是遇到偶發(fā)的情況或者傳入非法參數(shù)等原因掛掉),處理錯(cuò)誤的程序就可以讓它重新啟動(dòng),這樣系統(tǒng)又可以正常運(yùn)行了。這個(gè)哲學(xué)跟我們熟知的重啟可以解決90%以上問(wèn)題不謀而合。
(4) OTP框架
OTP 是包裝在Erlang中的一組庫(kù)程序。OTP構(gòu)成Erlang的行為機(jī)制(behaviors),用于編寫(xiě)服務(wù)器、有限狀態(tài)機(jī)、事件管理器。不僅如此,OTP的應(yīng)用行為(the application behavior)允許程序員把寫(xiě)好的Erlang代碼打包成一個(gè)單獨(dú)的應(yīng)用程序;監(jiān)測(cè)行為(the supervisor behavior )允許程序員創(chuàng)建樹(shù)狀結(jié)構(gòu)的進(jìn)程依賴(lài)鏈,使得某個(gè)進(jìn)程死后,它的監(jiān)控進(jìn)程(父進(jìn)程)會(huì)重新啟動(dòng)它而復(fù)活。
OTP提供大量通用的庫(kù)程序,可以輕松創(chuàng)建具有高度容錯(cuò)、熱機(jī)換碼等功能的高質(zhì)量高效的程序。你可以通過(guò)OTP獲得如下好處:
a 通用服務(wù)器、有限狀態(tài)機(jī)、事件管理器;
b 標(biāo)準(zhǔn)化應(yīng)用程序結(jié)構(gòu);
c 代碼熱機(jī)更換;
d 監(jiān)測(cè)樹(shù)行為機(jī)制,讓你的進(jìn)程永不”罷工“。
OTP是在Erlang之上構(gòu)建系統(tǒng)平臺(tái)的標(biāo)準(zhǔn)方式。大型Erlang項(xiàng)目,如ejabberd, CouchDB等,都是基于OTP開(kāi)發(fā)的。我們的視頻推薦系統(tǒng)也大量利用OTP的各種行為機(jī)制,這樣只需要實(shí)現(xiàn)核心的接口,進(jìn)程間的調(diào)用、監(jiān)控這些能力行為機(jī)制很容易幫我們做到。
(5) 內(nèi)嵌的Mnesia數(shù)據(jù)庫(kù)
Mnesia是內(nèi)嵌入Erlang的一款容錯(cuò)的、分布式可拓展的交易型數(shù)據(jù)庫(kù),數(shù)據(jù)按照表來(lái)組織,類(lèi)似于關(guān)系型數(shù)據(jù)庫(kù),數(shù)據(jù)可以選擇存在內(nèi)存或者磁盤(pán)中,并且有一套自己的非常方便的查詢(xún)語(yǔ)言,可以對(duì)數(shù)據(jù)進(jìn)行方便快捷的讀寫(xiě)查詢(xún)等操作。
為什么選擇Erlang語(yǔ)言來(lái)開(kāi)發(fā)相似視頻推薦系統(tǒng)
有了上面對(duì)Erlang語(yǔ)言的簡(jiǎn)單介紹,我們?cè)谶@里簡(jiǎn)單介紹一下該項(xiàng)目采用Erlang語(yǔ)言來(lái)開(kāi)發(fā)的主要原因:
(1) Erlang語(yǔ)言有比較牛的互聯(lián)網(wǎng)應(yīng)用
大家耳熟能詳?shù)幕ヂ?lián)網(wǎng)軟件,如CouchBase、CouchDB(apache基金會(huì)上的一款文檔型數(shù)據(jù)庫(kù),類(lèi)似MongoDB),RabbitMQ(消息隊(duì)列中間件),還有基于XMPP協(xié)議的IM開(kāi)源軟件ejabberd等非常流行的軟件都是基于Erlang語(yǔ)言開(kāi)發(fā)的,它們?cè)?a href="http://www.1cnz.cn/v/" target="_blank">工業(yè)界有大量應(yīng)用案例。
另外大家可能知道whatsApp背后只有50多位工程師支撐近5億的月活用戶(hù)規(guī)模,在2014年被Facebook以190億美元收購(gòu)。而該公司背后用到的編程語(yǔ)言正是Erlang。當(dāng)時(shí),作者看到這個(gè)消息時(shí)是非常震驚的,對(duì)Erlang語(yǔ)言越發(fā)佩服了。
(2) Erlang語(yǔ)言的幾個(gè)特性非常適合該項(xiàng)目
前面對(duì)Erlang語(yǔ)言的特性做了簡(jiǎn)單描述,這些特性是構(gòu)建相似視頻推薦系統(tǒng)的核心基礎(chǔ),我們?cè)谶@里重點(diǎn)講一下對(duì)我們開(kāi)發(fā)該系統(tǒng)非常重要的一些特性。
Erlang屏蔽了跨服務(wù)器交互的細(xì)節(jié),內(nèi)嵌了跨服務(wù)器訪問(wèn)的rpc及網(wǎng)絡(luò)交換函數(shù),跨服務(wù)器交互跟與本地交互基本一樣,所以非常適合開(kāi)發(fā)分布式程序,能夠快速擴(kuò)展。
Erlang自帶非常多的數(shù)據(jù)處理函數(shù),方便對(duì)Set、List、Map、字符串等結(jié)構(gòu)的各類(lèi)操作。Erlang包含ETS、DETS等key-value的分布式數(shù)據(jù)結(jié)構(gòu)以及嵌入式數(shù)據(jù)庫(kù)Mnesia,非常方便對(duì)數(shù)據(jù)進(jìn)行讀寫(xiě)等操作。
Erlang的OTP框架和錯(cuò)誤處理機(jī)制也是非常的強(qiáng)大,適合開(kāi)發(fā)穩(wěn)定高效的應(yīng)用程序。
正是Erlang有這些成功的軟件產(chǎn)品、優(yōu)秀的應(yīng)用案例及非常有意思的特性,讓作者對(duì)Erlang崇拜不已,躍躍欲試,最終決定采用Erlang來(lái)開(kāi)發(fā)相似視頻推薦系統(tǒng)。對(duì)Erlang語(yǔ)言有興趣的讀者可以看參考文獻(xiàn)2,Erlang的作者寫(xiě)的一本全面介紹Erlang編程的書(shū),非常值得一讀。
系統(tǒng)架構(gòu)與工程實(shí)現(xiàn)
前面對(duì)相似視頻的算法實(shí)現(xiàn)細(xì)節(jié)及Erlang的特性做了完整的介紹,在本節(jié)我們就來(lái)詳細(xì)講解怎么基于Erlang的一些特性從工程上實(shí)現(xiàn)一個(gè)高效的分布式的Master/Slaver架構(gòu)的相似視頻推薦系統(tǒng)。
首先我們給出相似視頻推薦的架構(gòu)圖(見(jiàn)下面圖3),再針對(duì)每個(gè)模塊詳細(xì)說(shuō)明實(shí)現(xiàn)的細(xì)節(jié)。
圖3:基于Erlang語(yǔ)言的相似視頻推薦架構(gòu)圖
另外,整個(gè)項(xiàng)目的工程目錄如下圖,這里簡(jiǎn)單解釋一下:
conf是配置文件相關(guān)目錄,doc是文檔相關(guān)目錄,ebin是編譯文件目錄,log是日志目錄,Mnesia.helios@Platform-recommended-couchbase11是Mnesia數(shù)據(jù)存儲(chǔ)目錄,out是輸出相關(guān)目錄,RelevanceRecommend.* 、similarity_computing.app是工程啟動(dòng)及配置相關(guān)文件,src是源碼。
圖4:基于Erlang語(yǔ)言的相似視頻推薦工程目錄結(jié)構(gòu)
相似視頻推薦采用主流的Master/Slaver架構(gòu),主要包括Master、Slaver、Riak Cluster、Cowboy server 4個(gè)核心部分,其中Master、Slaver是整個(gè)相似視頻推薦算法的核心。Master主要負(fù)責(zé)任務(wù)的分配、跟Slaver保持聯(lián)系、并且從MySQL中將metadata同步到Mnesia中,而Slaver主要負(fù)責(zé)相似度計(jì)算,計(jì)算完后將推薦結(jié)果插入Riak集群中。我們?cè)谙旅娣謩e介紹這4個(gè)模塊的核心功能和實(shí)現(xiàn)細(xì)節(jié)。
Master節(jié)點(diǎn)模塊與功能
Master節(jié)點(diǎn)主要負(fù)責(zé)任務(wù)分派,數(shù)據(jù)同步,處理節(jié)點(diǎn)加入及退出等異常情況。Master包含4個(gè)主要組件,如上圖,各個(gè)組件的功能如下:
(1) data sync模塊
該模塊負(fù)責(zé)將需要計(jì)算相似性的視頻從MySQL(媒資庫(kù))同步到Slaver的Mnesia集群中,Slaver計(jì)算時(shí)直接從本地Mnesia讀取數(shù)據(jù)來(lái)進(jìn)行相似計(jì)算。由于需要參與計(jì)算的字段是較少的(媒資庫(kù)字段很多,我們只選擇同步對(duì)計(jì)算相似度有價(jià)值的字段),這里我們采用Mnesia的內(nèi)存存儲(chǔ),將所有數(shù)據(jù)存在內(nèi)存中,方便計(jì)算程序更快地從Mnesia讀取需要參與計(jì)算的視頻metadata,提升計(jì)算速度。
該模塊不光可以具備批量讀取MySQL所有數(shù)據(jù)的能力(項(xiàng)目第一次跑的時(shí)候需要全量計(jì)算),同時(shí)還需要實(shí)時(shí)監(jiān)控媒資庫(kù)的變化,如有新視頻加入,馬上(在秒級(jí)內(nèi))將新視頻同步到Mnesia中。
(2) add node模塊
當(dāng)加入新節(jié)點(diǎn)時(shí),通過(guò)重啟Master節(jié)點(diǎn),Master節(jié)點(diǎn)與新節(jié)點(diǎn)建立聯(lián)系,識(shí)別出新節(jié)點(diǎn),并把新節(jié)點(diǎn)加入計(jì)算集群,同時(shí)將Mnesia上的數(shù)據(jù)均勻分配到所有節(jié)點(diǎn)(包括新加入的節(jié)點(diǎn))、給新節(jié)點(diǎn)分派計(jì)算任務(wù)(如果當(dāng)前還有未計(jì)算過(guò)視頻相似度的視頻的話)。
(3) heartbeat模塊
Master節(jié)點(diǎn)定期(幾秒鐘)向所有Slaver節(jié)點(diǎn)發(fā)送心跳信號(hào),通過(guò)該信號(hào)探測(cè)Slaver是否活著,如果一段時(shí)間后Slaver無(wú)任何響應(yīng),Master會(huì)認(rèn)為該Slaver掛掉了,這時(shí)會(huì)將該掛掉的Slaver從計(jì)算列表中刪除,后續(xù)新的計(jì)算任務(wù)不再分配給該Slaver。
(4) Task allocation模塊
Slaver節(jié)點(diǎn)上啟動(dòng)多個(gè)(一般可以設(shè)置為該服務(wù)器核數(shù)的1-2倍,如4核機(jī)器,可以啟動(dòng)4-8個(gè)進(jìn)程進(jìn)行計(jì)算,有效利用多核計(jì)算能力)進(jìn)程進(jìn)行計(jì)算,等待Master節(jié)點(diǎn)來(lái)分配任務(wù)。Master節(jié)點(diǎn)定期跟Slaver節(jié)點(diǎn)通訊,輪詢(xún)各個(gè)Slaver節(jié)點(diǎn),了解Slaver節(jié)點(diǎn)是否空閑,如有空閑并且現(xiàn)在還有未完成的計(jì)算任務(wù),那么Master將新的計(jì)算任務(wù)分配給該slaver進(jìn)行計(jì)算。
(5) similarity update模塊
如果新加入的視頻A比視頻B相似列表中相似度最低的視頻相似度更大,這時(shí)我們就需要更新視頻B的相似列表,將A添加進(jìn)去,同時(shí)將B原來(lái)相似列表中相似度最低的剔除掉(見(jiàn)下面圖5)。
圖5:如果新視頻相似度大于某個(gè)視頻的相似列表,需要更新相似列表
那么怎么更新老視頻的相似推薦列表呢?一般來(lái)說(shuō),我們可以采用如下的方法,該方法也非常簡(jiǎn)單,容易理解。
在Master節(jié)點(diǎn)維護(hù)一張視頻id和它的相似列表最小相似度的表(見(jiàn)下表,表中的視頻都是已經(jīng)計(jì)算完相似推薦的視頻)。新加入的視頻A計(jì)算完相似視頻后(在計(jì)算topN相似度時(shí),保存A跟每個(gè)其他視頻的相似度),將A視頻與每個(gè)其他視頻的相似度與下表比對(duì),假設(shè)A與id_1的相似度大于s_1,那么就需要更新id_1的相似推薦列表了。
視頻id | 推薦列表最小的相似度 |
id_1 | s_1 |
id_2 | s_2 |
...... | ...... |
id_k | s_k |
實(shí)際上可以做很多簡(jiǎn)化,比如我們可以先求出上表中第二列的最小值(見(jiàn)下面公式),我們只保留A與其他視頻相似度大于?的視頻,其他視頻直接丟棄(其實(shí)很多視頻可以丟棄,畢竟很多視頻跟A是沒(méi)有任何相似度的),而不會(huì)影響更新計(jì)算邏輯,這些相似度大于??的視頻才是可能需要更新推薦列表的視頻。
? ? ??
Master節(jié)點(diǎn)除了上面5個(gè)核心模塊外,還維護(hù)兩個(gè)關(guān)鍵的數(shù)據(jù)結(jié)構(gòu):
A :living_nodes:記錄集群目前可用的Slaver節(jié)點(diǎn),如有有節(jié)點(diǎn)加入或者掛掉會(huì)更新該數(shù)據(jù)。
B:need_computing_id: 記錄哪些視頻還沒(méi)有計(jì)算相關(guān)視頻推薦列表,針對(duì)這些視頻在任務(wù)分配模塊中分派給Slaver節(jié)點(diǎn)計(jì)算,分配出去后將該視頻從待計(jì)算列表中刪除,避免重復(fù)計(jì)算。如果有新視頻加入,新視頻的id會(huì)寫(xiě)入該列表。
Slaver:主要負(fù)責(zé)計(jì)算任務(wù)
Slaver節(jié)點(diǎn)只有一個(gè)核心模塊,即計(jì)算模塊,負(fù)責(zé)根據(jù)Master節(jié)點(diǎn)指派的任務(wù)進(jìn)行相似計(jì)算。當(dāng)Master將某個(gè)視頻的計(jì)算任務(wù)分配到Slaver時(shí),Slaver從Mnesia讀取這個(gè)視頻的metadata信息,并計(jì)算該視頻與該視頻所在group(如電影組)的所有其他視頻的相似度,將相似度最大的TopN存到Riak集群中。
這里我們對(duì)核心的計(jì)算過(guò)程進(jìn)行更詳細(xì)的講解,讓大家知道我們是怎么解決TopN最相似視頻的計(jì)算問(wèn)題的。在下面圖6中每個(gè)Slaver節(jié)點(diǎn)中有4個(gè)worker(工作進(jìn)程,負(fù)責(zé)進(jìn)行相似計(jì)算),每個(gè)worker維護(hù)一個(gè)最大堆(最大堆中保留的元素個(gè)數(shù)就是我們需要計(jì)算的TopN的相似視頻數(shù)),最大堆負(fù)責(zé)保留最相似的N個(gè)視頻及相似度。
當(dāng)Master將某個(gè)視頻A分配給worker1時(shí),worker1先從Mnesia集群中將所有與A在同一類(lèi)別(如電影)中的所有視頻取出來(lái),循環(huán)計(jì)算與A的相似度,計(jì)算完一個(gè)就丟給最大堆,當(dāng)所有的視頻與A的相似度都計(jì)算完后,這些相似視頻都丟給了worker1維護(hù)的最大堆,根據(jù)最大堆的性質(zhì),最終最大堆中留下的視頻(及相似度)就是與A最相似的N個(gè)相似視頻了。
圖6:Slaver中進(jìn)行相似計(jì)算過(guò)程與邏輯
上面的最大堆是基于Erlang的ETS數(shù)據(jù)結(jié)構(gòu)及相關(guān)操作構(gòu)建的,它非常高效,也是我們整個(gè)計(jì)算引擎的核心子模塊,可以自動(dòng)對(duì)丟入的{(videoid(視頻Id),similarity_score(相似度))}結(jié)構(gòu)進(jìn)行排序,保留最相似的N個(gè)。上面提到worker中包含的計(jì)算部分,即是基于我們?cè)诘诙糠种械墓竭M(jìn)行計(jì)算的。當(dāng)某個(gè)視頻最相似的TopN計(jì)算完成后,worker會(huì)將推薦列表插入Riak集群,供前端接口調(diào)用。
這里面也是有很多可優(yōu)化點(diǎn)的,比如對(duì)于新聞或者體育等時(shí)效性很強(qiáng)的視頻,我們可以只從Mnesia中選取一段時(shí)間內(nèi)(比如過(guò)去1天)的視頻來(lái)計(jì)算相似度,這樣就不需要計(jì)算相似度時(shí)跟Mnesia中同一組中的所有其他視頻計(jì)算相似度,這樣大大節(jié)省了計(jì)算時(shí)間。再比如,如果計(jì)算相似度中標(biāo)簽的權(quán)重最大,我們計(jì)算視頻A與其他視頻相似度時(shí),如果A與其他視頻的標(biāo)簽相似度為0(或者很小),我們就沒(méi)必要計(jì)算它的其他維度的相似度了,直接將該視頻丟棄計(jì)算下一個(gè)。這些優(yōu)化點(diǎn)還很多,這里不一一描述。
Riak集群:負(fù)責(zé)最終相似推薦結(jié)果的存儲(chǔ)
Riak是基于Erlang語(yǔ)言開(kāi)發(fā)的一個(gè)分布式的key-value存儲(chǔ)系統(tǒng),可以非常容易地水平擴(kuò)展,非常適合大規(guī)模的數(shù)據(jù)存儲(chǔ),是整個(gè)相似視頻推薦系統(tǒng)的最終計(jì)算結(jié)果的存儲(chǔ)模塊,所有視頻的相似推薦列表都存在Riak集群中。Slaver的worker計(jì)算完一個(gè)視頻的相似度后會(huì)直接插入Riak。
相應(yīng)請(qǐng)求模塊:基于客戶(hù)端用戶(hù)請(qǐng)求,給出推薦結(jié)果
當(dāng)用戶(hù)在客戶(hù)端訪問(wèn)某個(gè)視頻的詳情頁(yè)時(shí),客戶(hù)端向服務(wù)端發(fā)送請(qǐng)求,請(qǐng)求響應(yīng)模塊根據(jù)用戶(hù)請(qǐng)求從Riak集群中將該節(jié)目的相似列表取出來(lái),并將其他需要的信息(如標(biāo)題、演職員、海報(bào)圖等在前端展示需要用到的節(jié)目metadata信息,這些信息我們存在Redis集群中)填充完整后返回給用戶(hù)。
請(qǐng)求響應(yīng)模塊是基于Cowboy (一款基于Erlang開(kāi)發(fā)的高性能輕量級(jí)接口服務(wù)器)來(lái)開(kāi)發(fā)的。從前面的介紹中可以知道,Cowboy除了從Riak中獲取推薦列表外,還需要從Redis中獲取節(jié)目的metadata信息做填充。
核心亮點(diǎn)
到此為止,我們基本講完了相似視頻推薦的核心算法原理與基于Erlang實(shí)現(xiàn)的工程架構(gòu),該系統(tǒng)是作者在15年開(kāi)發(fā)的,一直在作者公司的兩個(gè)產(chǎn)品中使用到現(xiàn)在,其中一個(gè)產(chǎn)品目前還是用的該算法(另外一個(gè)產(chǎn)品基于Spark平臺(tái)做了重構(gòu),整體效果更好),該算法在服務(wù)公司業(yè)務(wù)的4年中,雖然視頻種類(lèi)和數(shù)量有了非常大的增長(zhǎng),但是系統(tǒng)一直比較穩(wěn)定,也能夠很好地應(yīng)對(duì)視頻量的增長(zhǎng),并且效果還不錯(cuò),這得益于Erlang良好的容錯(cuò)機(jī)制及該系統(tǒng)較好的分布式擴(kuò)展能力。
在這里我們回顧一下該系統(tǒng)的亮點(diǎn),也讓我們可以更好地理解它的價(jià)值。
分布式可拓展能力
該系統(tǒng)采用Master/Slaver架構(gòu),可以通過(guò)水平地增加服務(wù)器來(lái)拓展該系統(tǒng)的計(jì)算能力,同時(shí)當(dāng)全量計(jì)算完后,后面就是增量計(jì)算了,增量計(jì)算相對(duì)沒(méi)有那么大的計(jì)算量,不需要這么多計(jì)算資源,我們可以縮減部分服務(wù)器節(jié)省開(kāi)支。
可以實(shí)時(shí)對(duì)新增加的視頻做計(jì)算
Master的Data sync模塊近實(shí)時(shí)監(jiān)控媒資庫(kù)MySQL,如果有新視頻加入,馬上將該視頻同步到Mnesia中,并分派給Slaver進(jìn)行計(jì)算,在分鐘級(jí)內(nèi)新視頻就可以完成計(jì)算,這樣基本可以有效避免新入庫(kù)視頻的相似推薦冷啟動(dòng)問(wèn)題。
系統(tǒng)很穩(wěn)定
該系統(tǒng)一般很少出問(wèn)題,這得益于Erlang的OTP框架,我們的Master和Slaver服務(wù)都是基于OTP框架來(lái)實(shí)現(xiàn)的,每個(gè)進(jìn)程都有一個(gè)supervisor進(jìn)程,當(dāng)進(jìn)程掛掉后,supervisor會(huì)重啟該進(jìn)程,避免了因?yàn)榕紶柕墓收匣蛘弋惓?shù)據(jù)導(dǎo)致的系統(tǒng)崩潰,最終讓我們的系統(tǒng)非常穩(wěn)定。
分將計(jì)算過(guò)程解耦合,抽象為最大堆來(lái)維護(hù)topN最相似的視頻列表
將計(jì)算相似性計(jì)算抽象為一個(gè)計(jì)算模塊,每個(gè)worker通過(guò)維護(hù)一個(gè)最大堆,可以非常有效地解決最相似的topN計(jì)算問(wèn)題。同時(shí),針對(duì)新聞、體育等時(shí)效性強(qiáng)的視頻類(lèi)型,我們還可以只取最近一段時(shí)間內(nèi)的視頻來(lái)計(jì)算相似度,進(jìn)一步減少計(jì)算量。
充分利用多核能力
每個(gè)Slaver可以啟動(dòng)多個(gè)worker進(jìn)行計(jì)算,充分利用現(xiàn)代服務(wù)器多核的能力,大大加速了計(jì)算過(guò)程。
除了上述優(yōu)點(diǎn)外,我們通過(guò)配置文件來(lái)定義各種參數(shù)(比如一個(gè)Slaver可以啟動(dòng)多少個(gè)worker),可以方便地對(duì)參數(shù)進(jìn)行調(diào)整,系統(tǒng)啟動(dòng)時(shí)會(huì)首先解析這些參數(shù)。我們也可以一鍵啟動(dòng)Master節(jié)點(diǎn)和所有的Slaver節(jié)點(diǎn),整個(gè)配置和啟動(dòng)過(guò)程跟Spark比較類(lèi)似。該系統(tǒng)可以看成基于Erlang語(yǔ)言開(kāi)發(fā)的具備特定功能的類(lèi)Spark的小型分布式計(jì)算平臺(tái)。
未來(lái)優(yōu)化方向
雖然該系統(tǒng)有很多優(yōu)點(diǎn),但由于個(gè)人能力及精力有限,并且對(duì)Erlang的了解還沒(méi)有達(dá)到爐火純青的階段,該系統(tǒng)還有非常多的地方是可以做優(yōu)化的。下面對(duì)可能的優(yōu)化點(diǎn)進(jìn)行說(shuō)明,作為后面努力的方向。
算法本身的優(yōu)化
該系統(tǒng)基于視頻內(nèi)容的簡(jiǎn)單向量空間模型來(lái)計(jì)算相似度,雖然算法原理簡(jiǎn)單,但是由于視頻的metadata比較雜亂,相似性效果受到數(shù)據(jù)質(zhì)量好壞的嚴(yán)重影響。同時(shí),向量空間模型是一個(gè)比較簡(jiǎn)單的模型,無(wú)法獲得更復(fù)雜的特征表示。可行的優(yōu)化點(diǎn)是,我們可以基于metadata數(shù)據(jù)或者用戶(hù)行為數(shù)據(jù)做嵌入,為每個(gè)視頻構(gòu)建一個(gè)稠密的特征向量表示,該系統(tǒng)可以通過(guò)稠密向量的相似度來(lái)計(jì)算視頻的相似性。其他各類(lèi)計(jì)算視頻相似度的方法都是可以使用的。
目前我們的計(jì)算相似度算法和整個(gè)系統(tǒng)還是耦合比較緊密的,通過(guò)優(yōu)化是可以將計(jì)算相似性做成可插拔的組件的,這樣就可以方便更換計(jì)算引擎。
另外,我們的向量空間模型各個(gè)維度的權(quán)重是根據(jù)人工經(jīng)驗(yàn)自定義的,比較主觀,其實(shí)是可以
利用用戶(hù)點(diǎn)擊反饋機(jī)制自動(dòng)化學(xué)習(xí)最優(yōu)參數(shù)的,這樣可能效果會(huì)更好。
調(diào)度策略的優(yōu)化
當(dāng)前該框架的調(diào)度策略還非常粗暴,對(duì)于每個(gè)需要計(jì)算相似推薦的視頻,直接從所有Slaver中先過(guò)濾出有空余資源的worker,將任務(wù)分配給第一個(gè)空閑的worker。針對(duì)每個(gè)視頻都要從頭過(guò)濾一遍,效率很低。
更好的方式是每個(gè)Slaver節(jié)點(diǎn)維護(hù)一個(gè)待計(jì)算相似度的固定長(zhǎng)度的視頻隊(duì)列,當(dāng)隊(duì)列中待計(jì)算的視頻都計(jì)算完了相似度,Slaver主動(dòng)向Master申請(qǐng)待計(jì)算的視頻。這樣將主動(dòng)權(quán)放到Slaver上,減少原來(lái)分配方案中毫無(wú)意義的輪詢(xún),同時(shí)也減輕了Master節(jié)點(diǎn)的壓力。
部署方式的優(yōu)化
目前的系統(tǒng)雖然部署非常容易,只要在每臺(tái)服務(wù)器上安裝Erlang,將該項(xiàng)目編譯好,將編譯后的工程代碼分發(fā)到每臺(tái)服務(wù)器上統(tǒng)一的目錄下,修改每臺(tái)服務(wù)器上的配置文件(實(shí)際上所有Slaver上配置是一樣的,跟Master上略有不同)就可以啟動(dòng)了。
更好的方式可以利用docker將工程構(gòu)建在容器之上,利用mesos或者kubernetes等來(lái)管理工程運(yùn)行,可以更好地做到集群監(jiān)控和資源彈性伸縮。
錯(cuò)誤監(jiān)控與問(wèn)題排查的優(yōu)化
目前該項(xiàng)目運(yùn)行過(guò)程中會(huì)打少量的日志記錄,但對(duì)于各個(gè)模塊中可能存在的錯(cuò)誤信息并未捕獲并記錄下來(lái),對(duì)于問(wèn)題的發(fā)現(xiàn)和排查不是很友好。雖然Erlang很穩(wěn)定,但是偶爾出一些問(wèn)題是在所難免的,這一塊的優(yōu)化也是未來(lái)可行的方向之一。
數(shù)據(jù)同步的優(yōu)化
目前是由Master節(jié)點(diǎn)的data sync模塊直接監(jiān)控MySQL(媒資庫(kù)),從中將數(shù)據(jù)同步到Mnesia集群的。這一塊是可以直接采用消息隊(duì)列(如RabbitMQ)解耦的,data sync只需要監(jiān)控消息隊(duì)列中某個(gè)topic是否有新節(jié)目進(jìn)來(lái),有新的話就同步到Mnesia中,這比直接監(jiān)控MySQL高效得多。
后面作者會(huì)考慮基于上面幾點(diǎn)優(yōu)化思路對(duì)該項(xiàng)目進(jìn)行優(yōu)化,同時(shí)對(duì)代碼結(jié)構(gòu)進(jìn)行調(diào)整,讓代碼看起來(lái)更加優(yōu)雅,如果有機(jī)會(huì)的話是希望可以將該項(xiàng)目開(kāi)源的。
個(gè)人收獲與感悟
到此為止,關(guān)于利用Erlang語(yǔ)言開(kāi)發(fā)分布式視頻相似推薦系統(tǒng)的介紹就講完了。在最后作者簡(jiǎn)單說(shuō)下自己做這個(gè)項(xiàng)目后的收獲和感悟。
作者在2015年花了近半年時(shí)間,算是一邊學(xué)習(xí)Erlang語(yǔ)言(在這之前看過(guò)Erlang,但是看得不太懂)一邊開(kāi)發(fā)了該項(xiàng)目。該項(xiàng)目一共5000行左右代碼,雖然不是很多,但是對(duì)于像Erlang這類(lèi)簡(jiǎn)潔的語(yǔ)言來(lái)說(shuō),也不算少(如果用Java實(shí)現(xiàn),估計(jì)要幾萬(wàn)行,還很難實(shí)現(xiàn)分布式計(jì)算)。在整個(gè)開(kāi)發(fā)過(guò)程中,最大的收獲有如下3點(diǎn):
新學(xué)習(xí)了一門(mén)比較有意思的函數(shù)式編程語(yǔ)言,對(duì)Erlang的特性有了比較深入的了解;
對(duì)于分布式計(jì)算有了更深刻的認(rèn)識(shí),這個(gè)項(xiàng)目相當(dāng)于獨(dú)立實(shí)現(xiàn)了一個(gè)小型的分布式計(jì)算引擎,對(duì)于深刻認(rèn)識(shí)Spark、Hadoop的原理是非常有幫助的;
獨(dú)立完成了一個(gè)較大的工程,并且實(shí)現(xiàn)了一個(gè)基于內(nèi)容的相似視頻推薦系統(tǒng)。
做完該項(xiàng)目對(duì)個(gè)人來(lái)說(shuō)確實(shí)是非常有幫助的。但是從整個(gè)團(tuán)隊(duì)來(lái)說(shuō),這樣做未必是好事,利用一個(gè)很小眾的語(yǔ)言來(lái)開(kāi)發(fā)一整套系統(tǒng),為以后埋下了很大的隱患,如果人員離職,很難招聘到Erlang的開(kāi)發(fā)人員,新人很難獨(dú)立維護(hù)這套系統(tǒng),風(fēng)險(xiǎn)極大。作為團(tuán)隊(duì)管理者,應(yīng)該避免這種情況發(fā)生,最好還是利用主流的技術(shù)棧,避免留下無(wú)窮后患。
當(dāng)時(shí)作者管理經(jīng)驗(yàn)還不足、對(duì)技術(shù)的理解還不夠深入,所以自告奮勇的親自開(kāi)發(fā)了該系統(tǒng)。經(jīng)過(guò)這幾年的積累和成長(zhǎng),對(duì)技術(shù)和管理有了更深的感悟。如果作為一名技術(shù)管理者,讓我再一次選擇,我可能不會(huì)用Erlang來(lái)開(kāi)發(fā)該系統(tǒng),而會(huì)采用Spark流式計(jì)算引擎來(lái)開(kāi)發(fā)。
-
視頻
+關(guān)注
關(guān)注
6文章
1942瀏覽量
72884 -
算法
+關(guān)注
關(guān)注
23文章
4607瀏覽量
92835 -
erlang
+關(guān)注
關(guān)注
0文章
16瀏覽量
5742
原文標(biāo)題:基于Erlang語(yǔ)言的視頻相似推薦系統(tǒng) | 深度
文章出處:【微信號(hào):rgznai100,微信公眾號(hào):rgznai100】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論