Airbnb个性化搜索服务架构
導語:業務快速增長給搜索帶來什么樣的挑戰?針對類似場景如何設計通用的平臺?本文詳細講述Airbnb大型搜索服務的演進之路。
去年,Airbnb到了需要可擴展、分布式存儲系統的時候了。例如,搜索個性化數據超過了單機的承載能力。當我們提升了個性化服務的縱向擴展能力的時候,意識到其他服務也有同樣的需求,因此決定設計一個通用平臺,簡化其他服務需要做的事情。
除了通常的請求/響應模式,其他服務有不同的需求,例如,從數據源(例如,MySQL數據庫)做周期性批量同步,引入新的數據源(例如,新的搜索特性),從數據流中消費增量更新(我們的場景中是Kafka),或者提供數據分析能力,并且為網站流量提供低延遲的數據服務。隨著公司的持續增長,我們有很多應用積累了越來越多的數據。如果我們能挖掘出有用的信息并且反饋給應用,那么這些數據可以為我們的產品提供巨大價值。
摘要
讓我們從個性化搜索開始。這需要保留我們的用戶行為歷史。要求能記錄實時用戶行為,并且能立即獲得記錄,以優化個性化搜索結果(并且改善其他產品)。提供其他應用能用的數據快照(例如分析或者驗證)。需要周期性的聚合并且截斷歷史數據,批量導入一批特征(離線計算)到系統中。
這些需求貫穿公司很多應用。因此我們決定設計一個通用存儲平臺,以支持這些需求,并幫助其他服務負責人聚焦他們特殊的業務邏輯。我們計劃在這個系統中滿足下面這些需求:
為網站流量提供低延遲操作(毫秒級別)
實時數據流提供增量更新
便捷高效的數據批量操作
保證公司增長的數據和流量可擴展
維護成本小
注意,我們將“批量操作”定義為快照和壓縮完整存儲庫的操作,用新快照替換現有快照以進行服務,將完整的新信號合并到存儲庫中,用新集合替換現有信號數據以及完整數據集上的任何其他操作。Nebula是一個平臺,我們這個存儲上滿足了所有的這些需求。
?
什么是Nebula?
Nebula是一個無模式版本化的數據存儲服務,提供實時隨機數據訪問和離線批量數據管理。它包含一個支持增量數據(最近一段時間的更新)的動態數據存儲的獨立服務,和一個支持批量操作的靜態數據存儲的快照數據存儲。我們選擇DynamoDB作為動態數據存儲(主要原因是它有很低的讀延遲,使用AWS的維護成本低),和HFileService(Airbnb內部使用的可擴展的靜態存儲,支持分區和本地硬盤到HFile格式的預處理)存儲靜態的快照。
?
隨機數據訪問的抽象存儲
Nebula為底層物理存儲提供了統一的API。API為應用提供了通用K-V存儲API,增量和靜態數據內部合并,這樣,應用不需要為實時數據和批量數據分別部署。所以,它能靈活的遷移到不同的物理存儲,上層應用不需要修改API。
Nebula使用版本化列式存儲,類似于BigTable和HBase。版本化列式存儲比起原始K-V存儲,能讓服務負責人更便捷地定義他們的數據模型。必要的時候,版本能解決沖突和跟蹤數據變更時間。應用每行和列能存多少個版本沒有任何限制。
Nebula支持<行,列,版本>級別的原子操作。并發寫同樣的<行,列>會有不同的版本,這樣數據能合理的存儲。每列都有自己的版本,并且所有的寫直接追加到各自的列上(通過版本存儲)。用戶隨機訪問需要通過給定<行,列>獲取一個或者多個版本的數據。獲取多列或者多行的多次請求可以合并到一個單獨的多請求中。
使用個性化數據的一個例子,數據模型如下:
每行表示一個用戶的數據,每列表示一個用戶交互類型(又叫用戶事件),比如前面提到的搜索,每個版本是用戶事件發生時候的時間戳。在產品中,我們有很多用戶事件,每個事件列積累了大量的不同時間戳的事件。
為了支持一個搜索請求,搜索服務查找給定用戶對應的事件數據,用這些個性化數據在排序模型中決定向用戶展示的有序列表。因為這是搜索請求路徑,所以我們有很嚴格的延遲和可用性要求。
數據能通過增量數據流(包含個人用戶事件)以單元格為單位和離線管道批量(壓縮歷史數據或者按列引導/合并/替換數據)的方式被更新。
?
內置批量數據處理
Nebula使用離線管道為每個倉庫的增量數據做快照,與前面的快照合并,然后使用新的快照提供服務。這些任務跟在線服務分開執行,對網站流量的影響非常小。
管道可以根據要求進行高級配置。例如,每個應用可以定義他們自己的策略,如何合并新老數據(例如,新數據覆蓋老數據,使用版本聚合,丟棄老數據等等),如何壓縮歷史數據(保留N個版本,刪除某段時間之前的數據等等),如何調度管道,等等。
Nebula給用戶提供定義良好的接口,用于他們定制數據并且自動加載到系統中。用戶可以將他們的數據放在公共的地方,修改一些Nebula配置,然后管道將選擇并且合并數據到系統中以供使用。
應用負責人能在數據快照上,將他們的特殊需求定制的邏輯放到管道上。他們的邏輯將在最新的快照數據上執行,所以,這是一個處理邏輯的有效方式。
在個性化搜索場景中,我們在下列情況下使用管道:
定期生成快照,合并增量數據和靜態數據
按列進行壓縮和過濾過期事件,保證數據大小可控
離線特征計算以創建新的特征,批量導入新特征到存儲中
定制驗證用戶事件的邏輯,合理的狀態檢查
所有的個性化數據都版本化,不管什么時候發現數據問題,Nebula可以回滾到以前的好快照,并在版本(時間戳)之前丟棄任何不良數據。回滾邏輯根據應用決定,但是Nebula的批量接口讓回滾邏輯實現很簡單。
?
架構
這是整個系統的架構(如下)和設計選型。
一個Nebula讀請求查詢兩個數據源。增量數據存儲僅僅包含最新的數據,快照存儲包含完整的數據。兩個存儲都支持讀查詢,但是只有動態存儲接收寫請求。快照存儲的更新通過切換底層快照。數據存儲通過Zookeeper協作。
?
動態數據存儲DynamoDB
我們選擇DynamoDB是因為低延遲的要求,但是也可以根據其他要求使用其他的物理存儲(例如HBase)替換。作為Nebula的底層存儲,物理存儲只需要支持主鍵和排序二級索引。盡管底層實現不同上層接口卻是一致的,對于系統上的任何應用(和用戶)來說,替換物理存儲是透明的。
我們不準備去設計另外的物理存儲,使用DynamoDB作為底層的存儲能讓我們非常快速的組建一個系統。
數據輸入流被寫入動態存儲中;它允許隨機更新,并且支持很高的QPS。DynamoDB的讀延遲很低,所以能很好的滿足我們平均10毫秒的延遲要求。我們做了一個優化,為了保證DynamoDB表的大小容易管理,每天將數據分區到新的表。所以,我們的每個表僅僅占據一部分DynamoDB的分區以保證有高的QPS。
?
批量數據存儲HFileService
Nebula根據動態更新合并起來的實時查看的最新快照存儲在HFileService集群中。
HFileService以低延遲高吞吐量從本地磁盤中提供靜態的HFiles(快照格式)。而且,數據加載過程對讀請求幾乎沒有影響,所以離線數據合并操作不影響對數據的實時訪問。
HFileService通過動態分片機制對數據分區,所以水平擴展能力依賴數據的總大小。盡管是靜態數據,復制策略非常簡單并且能隨著流量的增長去調整。
?
使用離線管道做快照、壓縮和定制邏輯
Nebula支持在線隨機數據訪問和批量操作。批量操作不影響在線訪問。下圖描述Nebula的離線架構:
定期從增量存儲導出批量更新數據到分布式文件系統(Amazon S3)。數據導出之后,啟動一個離線Spark任務將批量更新和歷史數據合并。我們經常有其他的離線產生數據的情況,例如機器學習特征,需要批量上傳到系統中。合并階段經常有這樣的情況,新快照通過合并批量更新、歷史數據和定制離線數據進行創建。我們在合并過程中添加合理的檢查,避免壞數據進入到我們的系統。
最新的快照存在S3上,等待下一輪合并。它也會被保存到我們的歷史數據存儲中。貫穿整個導出-合并-加載過程,實時存儲一直保留這些導出到S3的增量數據,直到新的快照生成成功并且保存到歷史數據存儲中才會刪除。這保證了讀請求總通過實時和歷史存儲能獲取到完整數據。
S3上的完整快照被用于其他的離線數據分析。
?
流式更新輸出
除了對快照的隨機訪問和批量處理,Nebula還支持流式更新,以保證應用及時感知數據的更新。通過DynamoDB的流API來支持流式更新。一個單獨的組件使用Kinesis消費者中的流,并將其發布到特定的Kafka流中,因此任何感興趣的服務都可以訂閱它。
?
其他場景:搜索索引基礎設施
說完了Nebula,接下來講講我們如何使用Nebula重構Airbnb的搜索索引。我們先聊一下為何要重構。
由于Airbnb大部分使用Rails / MySQL作為前端,因此搜索索引會監聽(并且仍然)對數據庫表進行更改,維護當前搜索索引文檔的緩存,并使用新文檔更新搜索實例(如果有任何更改)。由于使用輪詢加載器加載,以及從數據一致性的數據源定期同步,因此性能不確定。新的搜索機器可以通過從緩存中緩慢流式傳輸來引導其索引。
下面是我們決定使用這個系統的原因:
端到端的低延遲操作(平均時間小于1秒)
能夠通過批量任務離線處理并且合并消費的特征到索引中
能夠使用實時特征
離線生成索引(能夠共享索引到離線分片)
快速回滾有問題的分片
快速擴展新的搜索實例
審核搜索索引文檔的更新
索引數據增長的時候可擴展
Nebula系統上面的這些特性很完美的解決了我們所有的需求。版本化列式存儲意味著我們能審核搜索文檔,支持批量任務意味著我們能離線生成索引(以及合并列表特征)并且直接部署到搜索中。因為這些索引基于快照構建和部署,出現壞的索引數據我們能快速的回滾。新生成的索引被用于新的搜索實例快速啟動(僅僅通過下載索引)。
上圖展示了基于Nebula的搜索架構。數據快照作為離線數據合并的一部分每天生成。索引構建器的作業對此快照進行操作以構建分片索引,然后像普通的二進制部署一樣定期部署搜索。這個系統使用了Nebula的特性,只需要實現定制邏輯關聯搜索索引。
?
展望
我們在Nebula之上構建了很多服務,包括剛剛提到的搜索索引管道,個性化基礎設施,Airbnb的價格服務數據倉庫。為每個應用提供了很多TB的數據,平均延遲在10毫秒。我們想鼓勵其他的團隊使用Nebula構建更多的應用。
我們也計劃把我們的系統跟我們的數倉深度結合,即,存儲歷史快照到Hive,共享更多數據流消費邏輯,等等。為分析功能提高數據的可用性和一致性,讓系統管理和操作更便捷,這樣對開發者來說才能更容易構建他們的應用。
?
鳴謝
很多人的付出才把這個系統做起來。我們想感謝Alex Guziel為這個項目所做的突出貢獻,感謝Jun He, Liyin Tang, Jingwei Lu等人的慷慨相助,還有很多人通過搜索,應用基礎設施,數據基礎設施,產品基礎設施和其他團隊所有以各種方式幫助的人。
?
原文地址:
https://medium.com/airbnb-engineering/nebula-as-a-storage-platform-to-build-airbnbs-search-backends-ecc577b05f06
總結
以上是生活随笔為你收集整理的Airbnb个性化搜索服务架构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Cookie或将被替换!Chrome工程
- 下一篇: Envoy为什么能战胜Ngnix——线程