留意Netfix的推薦系統的架構,我們可以看到他們公司的推薦系統有明顯的分層,分別為離線、近線和在線推薦,各部分職責明確,共同為用戶提供推薦服務。將其系統做最大的簡化,剩下兩部分,離線計算和在線推薦服務,前者通過在內存或Hadoop中計算相似度(或者使用基于模型的方法)為后者提供推薦結果數據,而后者就是直接與外部系統進行對接的Web Service系統,把推薦結果數據返回給外部系統。
推薦系統的這一層對外服務接口將是本文闡述的內容。
關鍵詞: 推薦系統,WebService,NodeJS,Restify,推薦反饋
一. 概述
這一層對外服務接口需要做什么
主要職責:
- 接收外部系統的請求,從推薦結果數據中篩選出符合要求的數據,進行返回
- 根據請求,記錄ItemID、UserID和其它相關信息log
- 收集推薦反饋數據,如用戶點擊推薦商品的log
這一層的任務非常簡單,沒有復雜的業務邏輯,沒有耗時的計算任務(當然后期可以在這一層中加上簡單的模型計算)。因為這一層是直接對用戶負責的。我們都知道,盡管網站前端可以采用延遲加載的技術來請求推薦列表,但長時間得不到響應結果也是不可容忍的,因此這一層做得輕便、能夠快速響應成為了最終要的要求。
是否需要將推薦結果響應與推薦反饋分開不同的應用?
它們承載的是不同的任務,一個是將一輪推薦計算的結果呈現給用戶,一個是把用戶的反饋信息收集起來優化下一輪推薦計算。這么看來把兩者分開到不同的系統也是可取的,隨著系統日漸龐大,把兩個任務獨立開來會更便于維護和管理。但是在推薦系統搭建的初期,這兩者都只包含很小一部分的功能和代碼,那么把它們整合到一起也是可取的,只要代碼層次清晰明確,在項目前期也沒必要分那么細,系統多了還不方便管理。
二. 構建可靠的WebService
技術選型
使用什么語言什么框架都沒有所謂,這個年頭程序執行的性能瓶頸已經可以通過增加服務器解決了,但也不要選個不靠譜的,服務器還是能省就省,于是選個自己開發起來順手的語言就好了,這個時代代碼開發的速度比執行的速度更重要。
NodeJS在并發處理能力上還算比較出色的,關于它的討論在這里不展開闡述,這里介紹一個框架,Resity,它能夠快速地搭建一個REST風格的API服務,相比于Express等框架,它更顯輕量化,僅僅實現了API的功能,沒有分層沒有模板,響應更加迅速。
系統架構
NOTE:這一層的主要功能就是 1. 從數據庫讀取信息經過簡單地過濾返回給客戶端;2. 把客戶端請求的log記錄到數據庫中。
三. 可靠的代碼更新系統發布機制
進行NodeJS開發的朋友都了解Forever的使用,它是一個監控Node App的運行狀態的工具。
有以下幾個主要作用:
- 快速開啟、關閉項目;
- 在代碼更新時,便捷地重啟項目,但不支持熱部署;
- 代碼出錯導致服務崩潰,能重啟應用;
- 系統出錯,錯誤結束NodeJS應用進程時,能自動重啟應用;
- 后臺運行程序。
這就為集群的發布提供了便利。前面有一臺Nginx做引流,將后面的NodeJS服務器更新代碼后重啟這個步驟變得天衣無縫。
四. 問題探討及后續工作
關于數據庫
上文一直提及的數據庫,其實并沒有明確說明是使用哪個工具,它更加偏向于表示一套數據存儲的方案。可以使用MySQL存儲離線推薦的計算結果,可以在NodeJS和MySQL之間添加一層Redis緩存以提高查詢效率。這一套也只能勝任系統前期的壓力,項目發展到后期還會更改數據存儲的方案。其實這套存儲的方案更多的是根據項目和團隊的情況而定的。
關于推薦反饋
推薦系統對外服務層的數據庫充當的是在線層與離線層溝通的橋梁,推薦反饋的信息暫存在這一層的數據庫當中,還需要有定時任務將推薦反饋的數據抽取到離線的Hadoop集群當中,以便于提高下一輪推薦的效果。當然對于推薦系統的新用戶,由于沒有購買記錄,往往只能根據他最初的幾次點擊進行推薦,此時推薦的反饋信息又會作用于在線的推薦模型當中,產生實時推薦的結果。
參考文章
Netfix System Architectures for Personalization and Recommendation
文章列表