打造工業級推薦系統(六):構建優質的推薦系統服務

作者在之前的文章《推薦系統的工程實現》第三節中,對推薦系統業務流和各個模塊做了簡單介紹,相信大家已有初步的瞭解。

文章中簡單提到了推薦Web服務模塊,這一模塊也是直接與用戶交互的部分,在整個推薦系統業務流中具有舉足輕重的地位,因爲Web服務模塊的好壞直接影響用戶體驗。

本篇文章,作者會詳細介紹怎麼構建優質的推薦交互模塊,如何打造優質的推薦服務,更好地服務用戶。

任何一個優質的軟件服務都必須考慮高性能、高可用(HighAvailability)、可伸縮、可拓展、安全性等5大核心要素,推薦系統也不例外。

所以,我們會圍繞這5個點來說明,怎麼構建高效的推薦服務。

本文會從推薦服務背景介紹、什麼是優質的推薦服務、構建優質服務面臨的挑戰、一般指導原則、具體策略等5個部分來展開講解。

希望讀者讀完本文後,對什麼是優質的推薦服務能有初步瞭解。同時,我也試圖爲讀者提供相應的方法和策略,期望本文可以作爲大家的參考指南。

推薦服務背景介紹

推薦產品是通過推薦服務來爲用戶提供個性化推薦能力的,我們可以從廣義和狹義兩個角度來理解推薦服務。

從廣義上講,推薦服務是指整個推薦業務,包括數據收集、數據ETL、推薦模型構建、推薦推斷、推薦web服務、推薦前端展示與交互等(見下面圖1)。

image

圖1:推薦系統的業務流

圖1中,大數據平臺包含的數倉、計算平臺等模塊很多公司(特別是初創公司和中小型公司)都是基於開源的大數據平臺(Hadoop、Spark、Hive等)來構建的,這些系統本身(或者通過增加一些組件)的設計是具備高可用、可拓展、可伸縮、安全等特性的。

同時,我們的數據ETL、推薦模型訓練、推薦模型推斷是基於數倉、計算平臺基礎之上構建的,也需要具備上面這些特徵,這部分我們在這裏不做介紹, 在未來分享推薦算法時會單獨講解。

從狹義上講,推薦服務是指用戶通過終端(手機、Pad、電視等)與推薦系統的web模塊的交互, 即圖1中紅色虛線框中的部分(其實Kafka管道不屬於直接參與Web服務的組件,但是我們是通過這個模塊來跟更底層的數據處理算法組件解耦合,通過它來對接計算出的推薦結果,所以也包括進來了)。

本文我們將主要精力放到關注推薦系統Web服務上, 即狹義上的推薦服務。

用戶與終端交互的過程見下面圖2,用戶通過終端請求推薦服務,推薦服務模塊通過返回相關的推薦結果給到終端,終端將推薦結果展示給用戶。用戶與終端的交互雖屬於視覺及交互設計範疇,與推薦工程師的工作無直接關係,但是會直接影響到用戶的體驗,也在我們討論之列。綠色虛線框中是真正的推薦系統Web服務過程。

image

圖2:用戶與推薦系統交互的數據流向

後文所有關於構建優質服務策略的主題,都圍繞這裏所指的狹義的推薦服務來展開。

簡單介紹完什麼是我們本文要討論的推薦服務, 那麼什麼是優質的推薦服務呢?我們又可以從哪些維度來衡量推薦服務是否優質呢?

什麼是優質的推薦服務

推薦服務作爲一類軟件服務,遵循通用的軟件設計原則。

在複雜的軟件設計中我們需要從高性能、高可用、可伸縮、可拓展、安全性等5個維度來衡量軟件架構的質量,對於推薦系統也一樣,推薦系統也屬於一類非常偏業務的較複雜的軟件系統,我們也會從這5個方面來說明什麼是優質的推薦服務。

01 高性能

所謂高性能,是指推薦服務可以在較短的時間內給用戶返回相關推薦結果,並且數據是準確可靠的,同時用戶會感覺整個交互過程很流暢,不會感到非常慢或者卡頓。

一般用響應時間(用戶觸發推薦頁面到返回推薦結果的時間)來衡量高性能,通常服務需要在200ms之內返回結果,否則用戶肉眼就可以直觀感受到慢了, 好的系統可以做到50ms之內返回結果。這個時間當然是越短越好,相應技術實現成本和難度都會更大。

當然,網絡會存在各種偶發情況,即使推薦服務性能很好,我們也沒法保證每個用戶請求都可以在這個時間內響應, 所以一般可以採用百分之多少的請求可以在多少毫秒內返回(比如99%的請求可以在75毫秒內返回)來衡量高性能。

02 高可用

所謂高可用,從字面理解就是用戶可以一直使用而不出現問題。

由於軟件服務是基於現代芯片及硬件基礎上構建的,硬件會產生故障宕機,軟件也會由於bug或者偶發情況等出現問題,所以一般故障是幾乎無法避免的,特別是對於大規模分佈式服務,共同服務於同一服務的計算機集羣越大,出現故障的可能性也會越大。

這裏舉個例子:比如飛機是最安全的交通工具,但是一兩年基本都有一些飛機相關的事故,主要是全球每天有大量的航班飛行,雖然單次飛行出問題概率非常小,但一兩年累計下來至少一次飛行出問題的概率就很大了,學過概率統計的讀者應該很好理解。

當這些故障出現時,軟件系統將無法響應用戶請求,導致提供的服務不及時、不穩定、不可靠,甚至不可用。

計算機行業的高可用一般是通過故障出現後的影響時長、等級及故障恢復的快慢來衡量一個軟件系統是否高可用。如果故障不頻繁、故障影響面不大、在很短的時間就恢復正常了就是高可用的系統,否則就不是高可用的系統。

很多大型網站,比如淘寶,百度基本達到了99.99%的高可用了,算下來一年大約只有0.88小時不可用。

推薦系統本身就是一項軟件服務,對於推薦系統來說,高可用就是推薦服務是否穩定高效的爲用戶提供服務。

03 可伸縮

我們可以這樣來理解伸縮性, 將一個模塊或者系統類比爲一條生產線(如富士康中蘋果手機生產線),當有大量的訂單需求時,可以通過擴充生產線來應對大規模的業務需求,這就是生產線的伸縮性。

推薦系統需要面對海量用戶的推薦請求, 同時也要爲每個用戶存儲相關的推薦結果。可伸縮性是指是否可以通過不斷增加服務器(在該服務器上部署相關的推薦服務)的手段來應對不斷新增的用戶及在服務高峯期暴增的請求。這種增加服務器來提供無差別的服務,必須是對用戶無感知的,不會影響用戶體驗。

互聯網產品(特別是toC互聯網產品)是基於規模效應的一種生意,發展用戶是公司最重要的事情,在用戶發展階段,用戶是爆發增長的,這時原有的推薦服務是無法滿足快速增長的用戶需求的, 所以要求推薦服務具備伸縮能力是必然的。

由於推薦系統需要存儲用戶推薦結果, 因此相應的存儲數據庫也需要具備可伸縮的能力,當前很多NoSQL數據庫都是具備可伸縮能力的。

04 可拓展

互聯網產品是需要快速響應用戶需求變化的,所以對產品做調整,或者增加新的產品形態是常有的事情。

可拓展性指的就是推薦服務可以快速響應業務需求變化,非常容易對服務做調整修改,可以非常方便地增加新的推薦業務。

比如,公司在前期沒有接入廣告,等做商業變現時,需要在信息流推薦中插入廣告,這時就需要對信息流推薦產品做調整,整合廣告投放能力。

05 安全性

互聯網是一個開放的服務體系,我們需要採用技術手段確保網站數據不會輕易被惡意攻擊,防止數據被盜。

衡量推薦服務安全性的主要指標是針對各種惡意攻擊及竊密手段是否有有效的應對方案,同時是否可以很好的保護用戶隱私,特別是今年315曝光了很多數據黑產的利益鏈,用戶數據安全性只會越來越重要,相信不久的將來,就會有更完善的法律保護措施出臺。

我們已經介紹完了好的服務設計需要具備的5大要素,這些要素是任何一個互聯網服務都必須關注的,更需要我們基於已有的人力資源、經驗、投入成本、業務特性等做好平衡。構建優質的推薦服務,也需要關注上面的5點,需要在這5大要素之間做好取捨和平衡。

相對於後臺服務,推薦服務是一種較特殊的軟件服務, 那麼對於推薦服務是否可以很容易做到上面5點呢?會面臨哪些挑戰呢?

設計推薦服務面臨的挑戰

相對於其他後臺系統來說,推薦系統有很多不一樣的地方。

對於個性化推薦來說,給每個用戶的推薦都是個性化的,所以生成的推薦結果都是不一樣的,這些推薦結果需要事先存儲下來,方便用戶請求時快速反饋給用戶,因此需要大規模的數據存儲系統來支撐。

特別是隨着短視頻、新聞APP的火爆,在這些產品中用戶消耗單個標的物的時長較短, 因此爲用戶提供近實時的推薦服務,並跟緊用戶興趣的變化,試圖佔用用戶的碎片化時間是這類產品設計中非常關鍵的要素,也是產品是否具備核心競爭力的先決條件。

具體來說,構建優質的推薦服務,會面臨如下挑戰:

01 需要存儲的數據量大

個性化推薦爲每個用戶存一份推薦數據,數據量隨着用戶線性增長。

一般toC互聯網產品都是通過規模效應盈利的,所以發展用戶是互聯網公司最重要的事情之一,做得好的產品用戶規模一定會在一定時期內爆發增長,因此數據存儲也會急速增長,需要更多的軟硬件資源來容納新增的大量數據。

當用戶量大到一定程度時,一臺服務器無法裝下所有用戶的推薦結果,一臺服務器也無法爲用戶提供web接口服務,這時就需要採用分佈式技術,需要數據庫及web服務系統具備很好的伸縮能力。

02 需要快速響應用戶請求

隨着新聞、短視頻等消費用戶碎片化時間的應用層出不窮,越來越多的推薦系統採用近實時的推薦策略,以提升用戶體驗,同時讓用戶沉浸其中,增加自己產品的使用時長,方便更好地拉投資或者做變現。

實時給用戶提供個性化推薦,這個過程中需要實時學習用戶的短期興趣,並基於用戶的短期興趣實時更新用戶的推薦列表,這爲整個推薦系統業務設計開發帶來極大壓力和挑戰。

03 接口訪問併發量大

個性化推薦由於每個用戶推薦結果都不一樣,很難利用現代CDN技術來對推薦結果加速(主要是命中率太低),用戶的請求一般都會回源,對後端系統產生較大的訪問壓力。

總的說來,有可能在極短的時間產生流量風暴。特別是對有些產品,由於產品自身的屬性,在特定時段訪問流量極大,比如視頻類應用,一般是晚上6-9點是訪問高峯,這時的流量可能會暴漲50%以上。

04 業務相對複雜

推薦業務爲了給用戶提供好的體驗,需要涉及到很多方面。

比如,需要具備根據一定業務規則做運營的能力。需要爲用戶過濾掉已經看過的或者曝光過的內容,需要對在推薦結果中下線某個標的物(如視頻中某個節目下線,電商中某個商品下線),需要實時根據用戶行爲更新用戶興趣推薦。這些較複雜的邏輯,對設計優質服務也是一種挑戰。

既然推薦服務的設計有上面這麼多挑戰,那我們要怎麼設計好的推薦服務呢?是否有一些一般的原則可借鑑呢?回答是肯定的。

構建優質服務的一般原則

在講具體的方法和策略之前,我們先簡單介紹一下做到優質服務需要了解的一般思路和原則,這些原則是幫助我們構建優質服務的指導思想。

01 模塊化(SOA)

SOA(Service Oriented Architecture)即面向服務的架構,主要目的在於服務重用,通過將服務解耦,提升整個系統的可維護性。

在設計系統時, 儘量減少系統的耦合,將功能相對獨立的部分抽提出來,通過數據交互協議或者接口與外界交互。這樣設計的主要目的是減少系統的複雜度,方便獨立對某個模塊優化和升級,同時,當系統出現問題時也可以快速定位。

最近幾年很火的微服務是對SOA思想的延伸,是一種輕量級的SOA解決方案,將服務拆解爲更細粒度的單元,更易於系統維護和拓展。

02 數據存儲

互聯網行業有所謂空間換時間的說法, 意思是通過將需要的結果預先計算好並存儲下來,等用戶請求時就可以直接返回給用戶而不需要再去計算,雖然佔用了存儲空間,但是大大加快了查詢速度。

而數據緩存就是一種空間換時間的做法,先將用戶需要的數據(對推薦系統來說,就是返回給用戶的最終推薦結果)事先計算好在數據庫中存起來。當用戶請求時,可以直接給到用戶。

涉及到緩存,緩存命中率就必須要關注了,如果一個查詢不會經常查到,緩存下來其實是沒有太多好處的,因爲以後也不會經常用到了。

個性化推薦產品每個用戶的推薦結果都不一樣,做緩存的價值是沒有那麼大的。但是對於關聯推薦,每個標的物關聯的標的物列表在短期(可能是一天)是不變的,這時就可以充分利用緩存的優勢了。

03 負載均衡

負載均衡(Load Balance),就是將請求均勻分擔到多個節點上執行,每個節點分擔一部分任務,整個系統的處理能力跟節點的數量成線性相關,通過增加節點可以大大提升整個系統的處理能力。推薦接口會大量採用負載均衡技術。

04 異步調用

舉個簡單的例子,你去銀行辦業務,拿到號後需要排隊,如果你一直看着屏幕等待你的號出現,這就是同步。如果你在等待的同時用手機處理工作郵件,等輪到你的號了銀行語音提示你去辦理業務就是異步。

從這個簡單例子可以看到,異步可以提升系統(這個例子就是你的大腦)的處理效率,而不必在一件事情上浪費時間。

在推薦服務中可以大量採用異步的思路,比如將推薦結果插入數據庫時,可以採用異步插入,提升插入的效率,響應接口請求時也可以採用異步處理。

由於異步不需要雙向確認,大大提升了效率,但是也可能由於沒有確認,導致部分處理請求失敗(比如某個用戶的推薦結果由於各種未知原因未插入數據庫)。

後面會講到推薦業務是可以容忍一定的錯誤的(不像涉及錢的會員等業務必須準確無誤),同時推薦業務需要處理大規模的數據(如T+1的個性化推薦,在一兩個小時內需要爲每個活躍用戶更新推薦結果,如果用戶規模很大,這個過程是很耗時的), 所以採用異步可以大大提升效率。

05 分佈式及去中心化

分佈式網絡存儲技術是將數據分散地存儲於多臺獨立的機器上。

分佈式網絡存儲系統採用可擴展的系統架構,利用多臺存儲服務器分擔存儲負荷,利用位置服務器定位存儲信息,不但解決了傳統集中式存儲系統中單存儲服務器的瓶頸問題,還提高了系統的可靠性、可用性和擴展性,這種組織方式能有效提升信息的傳遞效率。

通過將系統、數據或者服務分佈於多臺機器上,首先可以增強整個系統的處理能力,同時也可以降低整個系統的風險。

去中心化是互聯網發展過程中形成的一種內容或服務組織形態, 是相對於“中心化”而言的新型網絡內容的生產過程。在計算機技術領域,去中心化結構使用分佈式覈算和存儲,不存在中心化的節點,任意節點的權利和義務都是均等的, 系統中的數據塊由整個系統中具有維護功能的節點來共同維護,任一節點停止工作都不會影響系統整體的運作。

推薦系統的web服務和數據存儲都可以採用分佈式和去中心化的思想利用相關開源系統構建,如CouchBase數據庫就是分佈式去中心化的數據庫。

06 分層思想

分層跟模塊化思想類似,最大的區別是各個層之間是有直接的依賴關係的,分層一般也是根據邏輯結構、數據流、業務流等來分,即使是同一層內,也是可以做更細粒度模塊化的。

分層的目的是讓系統邏輯結構更清晰,便於理解、排查問題。推薦系統根據數據流就可以簡單分爲數據生成層、數據存儲層、數據服務層,後面會詳細介紹。

講完了設計優質服務的一般思想,那我們就來詳細講解一下具體有哪些策略可以幫助我們設計優質的推薦服務。

可行策略

我們在第一節中對推薦服務的範圍做了簡單限定,在第二節對優質服務的5個維度做了簡要說明,結合第四節的基本原則,我們在本節來詳細說明怎麼設計優質的推薦服務,有哪些具體的策略和方法。

設計優質推薦服務的目的是希望更好的服務於用戶, 提升整個系統的效能,最終提升用戶體驗。我們還是從高性能、高可用、可伸縮、可拓展、安全性5個維度來展開介紹。

高性能

爲了能夠提供高性能推薦服務,我們可以從如下維度來優化推薦服務模塊,以提升推薦服務的響應速度,給用戶更好的交互體驗。

01 CDN緩存

CDN(Content Delivery Network,即內容分發網絡)是一個非常成熟的技術,通過部署在各地的邊緣服務器來對內容進行加速。我們也可以利用該技術來加速推薦服務。

對於非個性化推薦(如排行榜、關聯推薦等),每個用戶返回結果都一樣,所以命中率極高,完全可以採用CDN來加速,以提升推薦接口的性能。

對於首頁上的T+1個性化推薦,由於用戶進入(是必經路徑,可能會經常回退到首頁)的概率較大,特別是很多APP,用戶一天多次登錄,也可以採用CDN做緩存(命中率可能沒有非個性化推薦大)。但是對於實時個性化推薦,每次刷新,推薦結果都不一樣,基本無法利用CDN的緩存能力。

CDN緩存雖然可以加速,但是利用CDN緩存也需要注意,如果某個請求出錯了,剛好被CDN緩存了,會對後來訪問的用戶產生負面影響(後來的用戶會返回這個被CDN緩存了的出錯的結果)。我們需要定期清理緩存,或者跟CDN廠商溝通,採用特殊的緩存策略(如返回的接口爲空或者不合法時不做緩存),最大利用CDN的優勢,避免不必要的問題。

02 Nginx層或接口層的緩存

除了CDN層的緩存,我們可以在Nginx層及接口web服務層增加緩存,採用多級緩存的策略能夠更好的避免請求擊穿緩存, 從而更快速的爲用戶提供推薦服務。

03 數據壓縮

如果某個推薦產品形態給用戶推薦的數據量比較大(比如,我們公司在做個性化重排序時,可能有幾百上千個視頻,用戶是通過分頁來請求的,數據量大,見下面圖3戰爭風雲這個tab,會根據用戶的興趣做個性化重排,用戶通過下滑遙控器按鍵分頁請求數據),可以對存儲於數據庫中的推薦結果進行壓縮(比如採用protobuf + base64進行編碼),這樣數據量就會少很多,減少網絡數據傳輸,提升接口性能。

image

圖3:基於用戶興趣的列表個性化重排序

04 接口做壓力測試

我們不光要驗證接口的功能是否正確(功能測試),還需要事先對接口的性能有所瞭解,知道接口的性能極限,這樣纔可以知道在高峯期間,所有推薦接口服務器是否能夠抗住壓力。

瞭解接口性能的最好方式是通過壓力測試。

通過壓力測試就可以知道接口在一定併發量下的吞吐率、響應速度、能夠承受多大的QPS。特別是個性化推薦接口,訪問量非常大,每次接口做升級或者開發新的推薦產品形態時,都需要做打壓測試。

我們基於打壓測試及在高峯時段用戶訪問情況, 纔可以確定到底需要多少臺接口服務器可以支撐現有的服務。

05 服務質量評估

推薦接口性能怎麼樣?是否有延遲,我們需要收集相關的數據來評估接口響應情況,總響應時間分爲兩個部分(見下面圖4)T1和T2,用戶的總響應時間T等於這兩部分之和(T=T1+T2)。

其中T1是網絡傳輸時間,衡量網絡情況,這部分時間基本是我們很難控制的(當然可以通過CDN加速, 提升出口帶寬來適當緩解)。

T2即是我們推薦接口響應時長,這部分時間包括從推薦庫中獲取用戶的推薦結果,並將結果組裝成前端展示需要的形式(拿視頻推薦來說,我們需要組裝出節目標題、演職員、詳情、評分、海報等前端展示時必要的信息)。

image

圖4:推薦服務響應用戶請求鏈路及時間花費

對於T2,我們可以在Nginx側記錄每次請求的響應時間,並將相關日誌收集到數據中心做分析,這樣就知道各個推薦業務接口響應情況。

下面圖5是我們自己的推薦業務相關接口性能統計情況(爲了隱私,隱藏了具體業務名稱、QPS及請求次數)。

從下圖可以看到很多接口99%的調用響應時長低於50ms,性能是很不錯的,但有些性能不是很好,如第四行的,只有81%的請求控制在200ms之內,這些業務都是非常老的版本的業務了,基本不再維護了。

從這張圖中,我們可以非常清楚地看到各個業務接口的性能情況, 這樣我們可以針對業務的重要性和當前性能情況做接口優化。

image

圖5:推薦接口性能統計

對於總時長T,我們也可以在前端通過日誌埋點記錄下來,同樣通過數據分析可以知道一個推薦業務平均耗時多少,總時間減去T2,就是T1的平均耗時,即網絡傳輸時間。

通過對服務質量評估,就可以有針對性的對上述的T1,T2做優化,從而提升接口性能。

06 採用高性能的web服務器

採用高性能的web服務器可以極大提升推薦服務的性能,推薦服務業務邏輯相對簡單,可以採用輕量級的web服務器,比如Vert.x(基於java語言的高性能web服務器)、Spray(基於Scala語言的高性能web服務器)、gin(基於Go語言的高性能web服務器)、cowboy(基於Erlang語言的高性能web服務器)等,這樣不僅可以滿足開發推薦接口的需求,開發速度快,並且性能也很好。傳統的web服務器如Tomcat等太重了,不太適合推薦api接口的開發。

07 採用基於內存的NoSQL數據庫

一般來說內存的訪問速度比磁盤快好幾個數量級, 採用基於內存的數據庫來存儲推薦結果會提升整個接口獲取推薦結果的速度,現在有很多開源的這類數據庫可供我們選擇,比如Redis、CouchBase等。

即使不用基於內存的數據庫,也要將數據存放到SSD中,獲取速度也會快很多。

高可用

構建高可用系統是一個比較有挑戰的事情,具體可以從如下方面來考慮:

01 接口層保護

即使有很多的防護策略,我們也不能保證推薦接口永遠也不出錯。

爲了應對這種在極端情況下可能存在的問題, 給用戶更好的體驗,我們可以在前端(即APP側)做一層接口保護。

具體做法可以是提供一組默認推薦接口,前端在啓動時加載該接口,將數據存儲在終端,當推薦服務無響應或者響應超時時,可以用默認推薦結果頂替。默認推薦雖然推薦的標的物沒有原來的精準,但是不至於“開天窗”,對用戶體驗也算是一個不錯的補救措施。

02 多可用區(多活)

對於創業中期或者成熟的公司,最好需要在多個可用區(同城多活,異地多活)部署推薦服務,避免由於自然災害(如工程建造挖斷光纜、爆炸、水災、火災、地震等)等導致服務無法使用。

構建多可用區需要投入非常多的資源, 成本較大, 對於初創公司建議不要考慮採用這種方式。

03 服務監控與自動拉起

服務監控的目的是保證在服務出現異常的時候第一時間通知運維或者相關負責人,在問題還沒有引起災難時儘快擴容服務器,或者有重大問題時,相關人員可以第一時間知道,快速解決問題。

有了自動監控,當服務出問題或者掛掉後,可以通過監控腳本自動將服務拉起。一般來說,重啓可以解決80%的故障問題。

04 灰度發佈

灰度發佈是互聯網公司常用的發佈策略,目的是通過先發布少量的用戶,看新功能點是否異常,如果有異常及時修復,不至於對所有用戶產生不好的影響。

對於推薦服務,我們也建議採用灰度發佈的方式,減少由於未發現的未知問題對用戶產生的傷害。

05 超時、限流、降級與熔斷

當推薦接口服務在一定時間(比如2s)無返回時,可以告知用戶訪問超時,避免一直等待導致的資源緊缺。

在極端情況下,當接口併發請求太大時(比如今年的春晚百度紅包), 可以對訪問請求做限制,讓部分請求立即執行,其他請求在隊列中等待。同時可以對同一IP的多次請求(可能是正常請求,也可能是惡意攻擊)做限制,減緩對接口的衝擊。還可以限制併發數、網絡連接數、網絡流量、CPU負載等各種限制措施來對訪問進行控制。

熔斷可以類比爲電錶的保險絲,當電流過大時(家裏太多電器同時用或者短路)保險絲熔斷,停止供電,避免出現意外事故。當請求推薦的服務有大量超時,這時新來的請求無法獲得響應,只會無謂的消耗系統資源,這時整個服務可能出現了異常,熔斷是較好的策略。

所謂降級,就是當服務不可用(比如熔斷後)時,採用效果更差的服務替代,雖然效果沒那麼好,但是至少比什麼都沒有強。上面提到的接口層保護就是一種降級策略。

採用超時、限流、降級、甚至是熔斷策略,主要是從系統高可用性角度考慮而採取的策略,目的是爲了防止系統整體緩慢甚至崩潰。

可伸縮

構建可伸縮的推薦服務,對於應對大規模的用戶請求非常必要,我們可以從如下方面來增強系統的可伸縮性。

01 利用NoSQL數據庫作爲數據存儲

由於推薦系統產生的數據量線性依賴於活躍用戶量,而互聯網產品DAU一般會很大(百萬級、千萬級、甚至億級),所以需要存儲大量的用戶推薦數據,並且這些數據是會頻繁更新的(對於T+1推薦每天更新一次,對於近實時推薦,可能會秒級更新), 所以採用一般的關係型數據庫是很不合適的。推薦的結果一般是爲一個用戶推薦一個標的物的列表,用關係型數據庫也不是特別合適,推薦的數據結構一般可以採用list,json等格式存儲。

基於上面的說明,這非常適合用現在的NoSQL數據庫做推薦結果存儲,現在很多NoSQL數據支持Json等複雜的數據格式,並且具備橫向擴容的能力。如常用的Redis,就支持String,Hash,List,Set,Sorted_Set等多種數據格式。

在我們公司的業務中,我們主要採用了CouchBase和Redis兩種NoSQL數據庫,CouchBase是一個文檔型分佈式數據庫,熱數據會放到內存中,冷數據會放到磁盤中,並且在水平拓展、監控、穩定性等方面做的非常好。我們將個性化推薦存儲在CouchBase中,非個性化推薦(如排行榜、關聯推薦等)存儲在Redis中。據我所知,在愛奇藝的推薦業務中也大量採用CouchBase。

02 接口web服務可橫向拓展

現在一般互聯網公司會利用Nginx的高性能特性做反向代理,通過Nginx代理推薦的web服務。

接口web服務最好做到無狀態,這樣就方便做橫向擴展。在我們公司實踐中,我們用Go語言的Beego框架和Gin框架來開發推薦接口,開發效率高,穩定,並且性能相當不錯,目前Go的生態圈非常完善,是一個不錯的選擇。

03 自動伸縮

推薦服務的可伸縮性要求我們可以非常容易地在負載高的時候做服務的擴容,結合現在的Docker容器技術及K8S編排系統及對接口服務的監控,制定一些伸縮的規則是可以做到自動伸縮的,當負載高時自動擴容服務器,當負載低時自動縮容。

這樣的好處是減少人工干預的時間, 及時伸縮也能更好的節省開支, 讓資源得到充分利用。當然,要想基於開源技術自己構建一套好用穩定的可自動伸縮的服務體系還是很有挑戰的,幸好現在很多雲計算廠商可以直接提供基於k8s、docker的雲服務,讓構建這樣一套系統變得容易起來。

可拓展

可拓展性衡量的是推薦系統應對需求變化的能力, 我們可以通過如下一些策略和思路讓推薦服務可以更好的拓展。

01 利用消息列隊減少系統耦合

在上面圖1, 我們通過一個Kafka管道的模塊來將推薦算法平臺與推薦數據存儲解耦合,而不是在推薦系統推斷階段直接將推薦結果插入推薦數據庫。這樣做的好處是減少系統依賴,便於問題排查。同時Kafka起到了對大規模推薦數據做備份和緩衝的作用。

02 利用解耦及庸才數據交互協議

將推薦系統服務儘量解耦,採用微服務架構,Nginx層、接口Web層、數據層等儘量獨立,採用符合業務規範(基於公司自己的業務特性及技術選型)的方式交互(比如利用http,thrift,protobuf等協議做數據交換)。這樣,對系統進行升級、維護、功能拓展、或者排查問題都非常方便。

現在業內有很多開源的微服務框架供大家選擇,如dubbo、Spring cloud等。也可以根據自己公司需要,自行開發滿足自己業務需求的微服務組件。

03 分層思想

我們可以簡單將推薦系統分爲三層,接口服務層處理用戶的請求,數據層存儲用戶的推薦結果,算法模型層構建推薦模型併爲用戶生成推薦結果(見下面圖6)。通過分層,讓整個系統更有層次感,更易於理解、升級、維護,也更方便排查問題。

image

圖6:推薦業務的分層模型

04 可適當容錯及服務降級

推薦服務跟涉及到錢的業務(如會員購買,廣告投放等)是不一樣的,推薦結果不夠精準最多是用戶體驗不好,不會有非常嚴重的投訴問題或者法律風險,所以推薦系統的容錯性相對要大一些。

基於推薦系統可容錯的特性及CAP理論(指的是在一個分佈式系統中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分區容錯性),三者不可兼得),推薦服務對一致性的要求也沒有這麼高,對於推薦系統選擇的分佈式存儲數據庫,不需要強一致性,往往達到最終一致性就足夠了,但是我們最好需要保證系統是滿足可用性的,這樣纔可以時時刻刻爲用戶提供推薦服務。

隨着產品的迭代,極大部分用戶可能會升級到相對較新的版本中,很老的版本用戶數肯定是較少的(相對於總用戶),對於這部分用戶,我們建議產品通過各種運營或者技術手段讓用戶升級上去,對於不升級的用戶,我們可以採用有損服務的形式爲它們提供推薦服務。具體方法主要有對這部分用戶關閉推薦服務和只爲這部分用戶提供默認推薦服務兩種方式,這樣做的目的主要是減少對推薦產品的維護成本。

所以,針對推薦系統可適當容錯及對低版本用戶可提供有損服務的特點,可以優化整個推薦系統的服務,讓部分服務簡化,間接提升了系統的可拓展性。

安全性

對於企業級服務,安全無小事,對於推薦系統同樣存在安全隱患,提升推薦服務的安全性可以從如下幾個維度來考慮。

01 接口安全

推薦服務可能由於受到攻擊或者可能存在的軟件bug導致對某個推薦服務的大規模請求。我們需要對推薦接口做保護,可以對同一IP地址的頻繁訪問做限制,或者對用戶鑑權,防止系統受到惡意攻擊。

對接口中涉及的隱私或者機密信息需要做加密處理。

同時,接口設計也要具備魯棒性,對獲取的推薦數據中可能存在的錯誤做異常保護,避免開發插入不符合規範的數據格式、數據類型等錯誤導致接口掛掉。

02 域名分流

對於用戶量較大的APP,我們可以通過域名分流的形式對推薦接口分流,當某個域名出問題,可以快速切換到另外的域名, 提供對接口更好的保護功能。

03 https

採用https協議而不是http,可以大大提升整個推薦接口的安全性,防止用戶信息泄露。https性能可能會有一定損失,但是相對安全性的提升是可以忽略的。但是採用https對開發及資金成本都有更高的要求。

04 現網驗證

當一個已有推薦業務做調整(接口調整、算法邏輯調整)或者新的業務上線後,一定要創造條件在現網驗證一下是否正常,確保接口可以正常返回數據,並且前端看到的數據跟接口返回的數據及數據庫中推薦的數據要保持一致。我們曾經出現過升級後未做驗證,發現前端數據不正常的情況。

寫在最後

本文從高性能、高可用、可伸縮、可拓展、安全性等5個方面對怎麼設計優質的推薦服務做了詳細講解,提供了一些思路和策略,希望爲設計推薦服務的讀者提供一些指導。

由於本人在軟件架構設計上實踐經驗有限,不當之處甚至錯誤在所難免,歡迎大家批評指正!

相關文章
打造工業級推薦系統(一):推薦算法工程師的成長之道
打造工業級推薦系統(二):無處不在的推薦系統
打造工業級推薦系統(三):推薦系統的工程實現與架構優化
打造工業級推薦系統(四):推薦系統怎麼更好的幫助公司掙錢?
打造工業級推薦系統(五):推薦系統冷啓動全解析

作者介紹:gongyouliu,有近 10 年大數據與 ai 相關項目經驗,有 9 年推薦系統研究及實踐經驗,目前負責電視貓大數據與人工智能團隊。喜歡讀書,暴走,寫作。業餘維護“大數據與人工智能”公衆號,ID:ai-big-data,持續輸出推薦系統相關文章。個人微信:liuq4360

原文鏈接:
https://mp.weixin.qq.com/s/XKocFaeu3E9diyfbT7w52A

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章