Spiral在Facebook通過實時機器學習自動調節服務
譯文【51CTO.com快譯】對于使用Facebook的數十億人來說,我們的服務可能看起來就像一個統一的移動應用系統或網站。從公司內部來看,情況卻不一樣。Facebook使用成千上萬的服務構建而成,從均衡互聯網流量、對圖像進行轉碼處理到提供可靠的存儲,功能不一而足。Facebook作為整體的效率在于結合了各項服務的效率,每項服務通常都以自己的方式加以優化,采用的方法可能很難推廣開來或適應快節奏的變化。
為了更有效地優化眾多服務,可以靈活地適應不斷變化、相互聯系的內部服務,我們開發了Spiral。Spiral這種系統充分利用實時機器學習的技術,在Facebook這等規模的環境下自動調節高性能的基礎設施服務。由于用Spiral取代了手工調節的啟發法,我們可以在短短幾分鐘內而不是幾周內優化更新后的服務。
應對規模挑戰的新方法
在Facebook,變化的步伐很快。Facebook代碼庫每隔幾個小時被推送到生產環境――比如前端的新版本,這是我們持續部署過程的一部分。當下變化萬千,試圖手動微調服務以保持峰值效率不切實際。手動重寫緩存/許可/驅逐(caching/admission/eviction)策略及其他手動調節的啟發法實在太難了。我們必須從根本上改變原有的軟件維護觀念。
為了有效地克服這個難題,系統需要變成自動調節,而不是依賴手動硬編碼的啟發法和參數。這種轉變促使Facebook的工程師們以新的眼光看待工作:工程師們現在不再查看系統生成的圖表和日志以驗證正確高效的運行,而是用代碼表達系統怎樣才算正確高效地運行。今天,我們的工程師通過編程實現向自我調節系統提供反饋的方法,而不是指定如何計算請求的正確響應。
傳統的緩存策略看起來像是帶有分支的樹,考慮到了對象的大小、類型及其他元數據,從而決定要不要緩存它。自動調節緩存將以不同的方式來實現。這種系統可以檢查某對象的訪問歷史記錄:如果之前從未訪問過該對象,緩存它可能是個壞主意。在機器學習語言中,使用元數據(特征)和相關反饋(標簽)來區分對象的系統將是“分類器”(classifier)。該分類器將用于針對進入緩存的對象做出決策,系統將持續被重新訓練。這種持續的重新訓練讓系統得以在即使環境發生了變化也能保持時效性。
從概念上來講,這種方法類似聲明性編程。SQL就是這種方法的一個典型案例:工程師不用指定如何計算復雜查詢的結果,只要指定需要計算的內容,然后引擎就會找出最佳查詢并執行查詢。
對系統使用聲明性編程的挑戰在于,確保正確完整地指定目標。與上述的自動調節圖像緩存策略一樣,如果什么對象應該緩存、什么不應緩存方面的反饋不準確或不完整,系統會很快學會提供不正確的緩存決策,這會降低性能。
幾位谷歌工程師撰寫的這篇論文(https://storage.googleapis.com/pub-tools-public-publication-data/pdf/43146.pdf)詳細介紹了這個問題以及與使用閉環機器學習有關的其他問題。根據我們的經驗,精準定義自動調節所需的結果是入手Spiral方面最棘手的部分之一。然而我們還發現,幾次迭代之后,工程師往往在清晰正確的定義上觀點一致。
Spiral:易于集成和實時預測
為了讓Facebook的系統工程師能夠跟上越來越快的變化步伐,Facebook波士頓辦事處的工程師們構建了Spiral,這是一個小巧的嵌入式C++庫,依賴項極少。Spiral使用機器學習為資源受限的實時服務創建數據驅動的反應式啟發法。與手工編碼的替代方法相比,該系統大大加快了開發和自動維護這些服務的速度。
與Spiral集成包括只需為代碼添加兩個調用點(call site):一個用于預測,一個用于反饋。預測調用點是用于做出決策的智能啟發法的輸出,比如“應該許可該條目進入緩存嗎?”預測調用作為快速本地計算來實現,旨在針對每個決策來執行。
圖1
反饋調用點用于提供偶爾的反饋,比如“該條目因根本未命中而失效退出緩存,所以我們可能不應該緩存這樣的條目。”
圖2
庫可以在完全嵌入的模式下運行,或者可以向Spiral后端服務發送反饋和統計數字,該后端服務可顯示用于調試的實用信息,將數據記錄到長期存儲供以后分析,以及執行訓練和選擇模型方面的繁重任務,這些模型在嵌入模式下訓練起來太耗費資源,但運行起來并不太耗費資源。
圖3
發送到服務器的數據采用反偏差采樣,避免類別不平衡偏差滲入到樣本中。比如說,如果一段時間內我們收到的負樣本比正樣本多1000倍,我們只要將1000個負樣本中的1個記錄到服務器,同時表示它的權重為1000。服務器深入了解數據的全局分布,通常帶來比任何一個節點的本地模型更好的模型。除了鏈接到庫和使用上面兩個函數外,這一切都不需要任何設置。
在Spiral中,一旦反饋進入,學習就開始。隨著生成的反饋越多,預測質量會逐漸提高。在大多數服務中,可在幾秒鐘到幾分鐘內獲得反饋,所以開發周期很短。主題專家可以添加新的特征,在幾分鐘內看看它是否有助于改進預測質量。
與硬編碼的啟發法不同,基于Spiral的啟發法可以適應不斷變化的條件。以緩存許可策略為例,如果某些類型的條目不太頻繁地請求,反饋將重新訓練分類器,以減小在不需要人為干預的情況下許可這類條目的可能性。
案例研究:反應式緩存啟發法實現自動化
Spiral的第一個生產級用例恰好吻合Phil Karlton的著名引言:“計算機科學界只有兩個難題:緩存失效和命名。”(我們已為自己的項目取了貼切的名稱,所以我們實際上使用Spiral立即解決了緩存失效。)
在Facebook,我們推出了一個反應式緩存,以便Spiral的“用戶”(我們的其他內部系統)訂閱查詢結果。從用戶的角度來看,該系統提供查詢結果和針對該結果的訂閱。只要外部事件影響查詢,它自動將更新后的結果發送到客戶端。這為客戶端減輕了輪詢的負擔,并減輕了計算查詢結果的Web前端服務的負載。
用戶提交查詢時,反應式緩存先將查詢發送到Web前端,然后創建訂閱,緩存并返回結果。除了原始結果外,緩存還收到計算結果時涉及的對象和關聯列表。然后,它開始監控針對查詢訪問的任何對象或關聯源源不斷的數據庫更新。每當它看到可能影響其中一個活躍訂閱的更新,反應式緩存會重新執行查詢,并將結果與緩存內容進行比較。如果結果確實發生變化,它將新結果發送到客戶端,并更新自己的緩存。
該系統面臨的一個問題是,有大量的數據庫更新,但只有很小一部分影響查詢的輸出。如果某個查詢想知道“我的哪些朋友贊過此帖?”,沒必要獲得“該帖最近一次查看”方面的持續更新。
這個問題類似垃圾郵件過濾:面對一封郵件,系統應該將它分類成垃圾郵件(不影響查詢結果)還是非垃圾郵件的正常郵件(確實影響查詢結果)?第一個解決方法是,手動創建靜態黑名單。這是可行的,因為反應式緩存工程團隊認識到超過99%的負載來自一小組查詢。對于低容量查詢而言,他們只是假設所有更新都是正常郵件,重新執行查詢,以便對象的每次更新被查詢引用。針對一小組高容量查詢,他們創建了黑名單,為此精心觀察查詢執行,確定每個對象中的哪些字段實際上影響了查詢的輸出。對于每份黑名單,這個過程通常需要工程師花幾周時間。使情況進一步復雜化的是,這一組高容量查詢在不斷變化,因此黑名單很快過時了。每當使用緩存的服務改變它所執行的查詢,系統就要改變垃圾郵件過濾策略,這需要工程團隊更多的工作量。
一種更好的解決方案:Spiral垃圾郵件過濾
重新執行查詢后,只要將新的查詢結果與舊的查詢結果進行比較,就很容易確定觀察到的更新是垃圾郵件還是正常郵件。該機制用于向Spiral提供反饋,以便它為更新創建分類器。
為了確保無偏差采樣,反應式緩存維護并只提供來自一小組訂閱的反饋。緩存并不過濾這些訂閱的更新;只要修改了相關對象或關聯,就重新執行查詢。它將新的查詢輸出與緩存版本進行比較,然后用它來向Spiral提供反饋――比如說,告訴它更新“上一次查看”并不影響“點贊數”。
Spiral從所有反應式緩存服務器收集該反饋,并用它為每種不同類型的查詢訓練分類器。這些分類器定期推送到緩存服務器。為新查詢創建過濾器或更新過濾器以響應Web層不斷變化的行為不再需要工程團隊的任何手動干預。新查詢的反饋到來后,Spiral會自動為那些過濾器創建新的分類器。
Spiral:更快的部署和更多的機會
使用一種基于Spiral的緩存失效機制,反應式緩存中支持新查詢所需的時間從幾周縮短到幾分鐘。在Spiral之前,反應式緩存工程師必須通過運行實驗和手動收集數據來檢查每個新查詢的副作用。但是有了Spiral,大多數用例(映射到查詢)可由本地模型在幾分鐘內自動學習,所以可以立即獲得本地推斷。
對于大多數用例而言,服務器能夠在10到20分鐘內使用來自多臺服務器的數據訓練模型。一旦發布到所有單臺服務器,這個更高質量的模型可用于精準度改進的推斷。查詢更改后,服務器能夠適應變更,一旦收到更新后的查詢,就重新學習新的重要性模式。
我們繼續致力于使后端服務實現自動化,并運用機器學習,以獲得更好的運營體驗。 Spiral未來的潛在應用包括使用貝葉斯優化的連續參數優化、基于模型的控制,以及針對每秒請求數(QPS)很高的實時服務和離線(批量)系統的在線強化學習技術。我們會在今后的帖子中繼續分享我們的工作和成果。
原文標題:Spiral: Self-tuning services via real-time machine learning,作者:Vladimir Bychkovsky、Jim Cipar、Alvin Wen、Lili Hu和Saurav Mohapatra
【51CTO譯稿,合作站點轉載請注明原文譯者和出處為51CTO.com】