1號店11.11:分布式搜索引擎的架構實踐
“11.11”是一年一度的電商盛宴,為了準備這個一年內最大規模的促銷,1號店各條戰線都在緊張有序地忙碌著。1號店搜索團隊經過幾年的大促歷練,不斷推動架構演進,積累了越來越多的經驗。
另,ArchSummit全球架構師峰會北京站將于2015年12月18日~19日在北京國際會議中心召開,大會設置了《 揭秘雙十一背后的技術較量 》專題來深入解讀雙十一背后的技術故事,歡迎關注。
11.11的主要特點是流量大和突發性高,這就帶來了兩個核心的需求:
-
可擴展
如何抗住這樣的流量,針對這個需求,1號店搜索團隊構建了分布式搜索引擎,支持橫向擴展;并且針對業務特點做了Routing優化,讓搜索的效率更高。
-
快速響應
流量越大,單位時間內的流量價值就越大,出現問題的損失也就越大,如何做到快速響應變得非常關鍵。針對這個需求,搜索系統支持自動部署和快速擴容以應對突發流量,索引數據從導入、處理到上線服務會經過層層驗證,同時還有監控體系及時發現線上的問題。
下面我們針對這些設計要點分別展開。
分布式搜索引擎
1號店分布式搜索引擎是Lucene/Solr核心的,結合SOA框架Hedwig構建了一層分布式框架,支持搜索請求的分發和合并,并且構建了搜索管理后臺,支持多索引管理、集群管理、全量索引切換和實時索引更新。
選擇自己構建分布式方案,而不是采用開源的SolrCloud或ElasticSearch,主要是基于以下幾點考慮:
(1) ElasticSearch/SolrCloud都適合于把搜索引擎作為一個黑盒系統來使用,而1號店搜索業務的展現形式多樣性很高,搜索條件有的會很復雜,有的需要通過自定義插件來實現,性能調優時也需要對引擎內部的執行細節進行監控。
(2) 將ElasticSearch/SolrCloud與公司內部的發布系統、監控系統和SOA體系結合起來,也是一項比較耗時的工作。
(3) 相對于整體使用,我們更傾向于把Lucene/Solr開源家族中的各個組件按需引入,一方面降低引入復雜工程的可維護性風險,另一方面逐漸深入理解這些組件,可以在必要時替換為定制化的組件。
分布式搜索是為了解決數據增長過程中索引變大和操作時間變長的問題,它將原來的單個索引文件劃分成n個切片(shards),讓每個shard都足夠小,從而保證索引可以在多臺服務器上部署,而且搜索操作可以在較短時間內返回。
如上圖所示,分布式搜索中有兩個主要組件:Shard Searcher和Broker,其中Shard Searcher與單機搜索引擎類似,基于Lucene/Solr完成基本的搜索任務。Broker負責把針對整個索引的搜索請求轉化為針對單個 Shard的搜索請求,它把Shard搜索請求分發給各個ShardSearcher,并且把各個Shard的結果進行合并,生成最終的結果。
分布式搜索中,一次搜索所需的資源與它要訪問的Shard數和每個Shard要返回的結果數有非常強的關聯關系,在Shard數特別多或結果數特 別多時可能會碰到一些的內存、CPU資源使用的問題。針對結果數特別多的情況,可以按照業務場景優化,比如如果對排序無要求,就可以每次指定一個 Shard進行搜索,搜完這個Shard再換下一個,這樣就限制了每次搜索的Shard數,另一方面也可以考慮使用DeepPaging等技術,減少每次 Shard搜索的成本。我們下一小節也會介紹1號店主站搜索是如何減少每次搜索Shard數的。
另外,上圖中的Broker和Shard Searcher僅僅是概念上的劃分,實際部署時有幾種選擇
A) 每個節點上都有Broker和部分Shard的Shard Searcher。
B) Broker單獨部署成一個集群,與Shard Searcher隔離。
C) Broker作為客戶端的一部分,和搜索應用一起部署。
我們開始使用的是A方式,后來主站搜索轉為C方式,主要是考慮到可以節省一次網絡調用(以及請求和結果的序列化開銷),另外Broker在客戶端也可以更多地使用應用邏輯相關的數據進行更高效的Routing。
高效Routing
通過前面的講述,我們不難看出,使用分布式搜索引擎,面臨的核心問題就是如何選擇高效的Sharding策略和Routing方案。為了設計Routing方案,我們需要深入理解業務場景。
1號店有很多的類目,每個類目的業務模式也不盡相同。以圖書和快消品為例,圖書是一種典型的長尾商品,它需要索引大量的SKU(Stock Keeping Unit,可以理解為一個獨立的商品),但每個SKU的訪問量和銷量都不高;快消品是另外一個極端,總體SKU數量不高,但是訪問量和效率都很高。這就造 成了一個不平衡的局面,圖書的SKU數目占比達到了50%以上,流量卻小于10%,我們就首先排除了按Shard數目取模(id mod N)這種平衡劃分的策略。
1號店搜索有兩個主要入口,一個是搜索框的搜詞,另外是類目導航。在這兩個入口中,類目的點擊肯定是訪問到一個特定的一級類目下,搜詞時用戶其實也只會關注相關的幾個類目。基于這種訪問模式,我們就采用了按照類目來切分Shard的策略。基本操作為:
(1) 按照一級類目切分Shard。
(2) 如果該Shard過大,則按照二級類目繼續切分。
(3) 經過前兩步之后,如果切分后的Shard過小,則按照相關性進行Shard合并。
經過這樣一番嘗試,Sharding策略就確定下來,切分之后的Shard索引大小一般為200~500MB,Shard上單次搜索可以控制在10ms以下。
接下來說到Routing,我們還是分搜詞和類目導航兩種場景,對于類目導航,原理上非常簡單,按照類目ID來查找Sharding策略,就可以 確定需要訪問的Shard,雖然現實中還需要考慮擴展類目等特殊場景,但是也不難做出一個簡單的Routing策略。再加上類目數是有限 的,Routing規則在Broker本地內存就可以緩存起來。
搜詞場景就復雜很多,僅憑詞本身很難判斷它屬于哪個Shard。我們首先按照詞的熱度分為兩類,采取不同的Routing策略。對于熱詞,搜詞流 量同樣符合80-20規則,20%的熱詞占比80%的搜索流量,對于熱詞,我們可以在建完索引之后,就跑一遍熱詞搜索,記錄那些Shard有結果,離線構 建出熱詞Routing表。切換索引時,Routing表也一起加載進去。對于非熱詞,則采用首次搜索去訪問所有Shard,根據結果記錄Routing 表,這個詞在下次搜索時,就有了緩存可用。
基本的Routing策略上線之后,通過監控每個Shard的訪問量,我們又發現了新的問題,圖書類目的訪問量比它應有的流量要高出不少。仔細分 析之后發現,由于圖書類目的特殊性,很多詞都可以在圖書中找到結果,然而這些結果一般都不是用戶想要的,實際上也不會排到前幾頁,并沒有展示的機會。于是 我們又增加了一種360-Routing策略,跟進搜索前五頁的結果(每頁72個商品,共360個商品)計算Routing,下次搜索時優先是用這份 Routing規則。由于前五頁的流量占比在80%以上,這就進一步減少了單次搜索需要訪問的Shard數。
使用了以上這些Routing規則,1號店主站搜索每次搜索平均只需要訪問1/3的索引數據,這就節約了2/3的資源,提高了搜索效率。
自動部署與快速擴容
文章一開始我們提到11.11要求搜索系統支持快速擴容,為了講清楚這個功能,我們首先要從索引部署講起。
按照類目進行Sharding和Routing的方式,在帶來高效的同時,也帶來了管理上的成本。按照類目切分,必然會導致各個Shard的大小 不平均,而對應的Routing方案,必然會帶來各個Shard的訪問量不平均。這兩個維度不平均就要求更加復雜的索引部署方案,主要的原則為:
(1) 首先根據流量比例和高可用的需求,確定每個Shard的副本數。
(2) 然后按照單個節點不能放置同一Shard的多個副本,節點上的承擔的流量總和與節點的服務能力成正比。
(3) 每個節點上的索引總大小盡量也保持差異最小。
按照流量比例,副本數計算如下:
Shard | 副本數 | 備注 |
S0 | 4 | |
S1 | 2 | 高可用約束 |
S2 | 4 | |
S3 | 3 |
部署之后的效果如下圖所示。
Shard數增多之后,人工計算部署方案就顯得較為復雜,于是我們就把部署方案生成做成了自動化,一個基本的Packing算法就可以完成這個工作。除了初始部署之外,自動部署工具還可以支持節點增加、減少和更換。
在11.11的場景下,這個自動化部署工具也可以支持快速擴容,基本過程為:
(1) Index Server(部署工具界面)計算出擴容之后的部署方案,寫入到ZooKeeper。這里的算法與初始部署有些不同,它需要保證現有服務器的Shard盡量不變。
(2) 每個Shard Searcher服務器都會監聽ZooKeeper上的部署方案,方案改變之后,Shard Searcher會獲取新的方案與本地方案對比,進行增減操作。
(3) Shard Searcher從HDFS上獲取索引數據,與最近的實時更新數據合并之后,啟動索引提供服務。
有了自動擴容工具,11.11容量規劃確定之后,新的服務器就可以很快部署上線,也減少了人工操作可能引入的失誤等問題。大促期間如果需要緊急擴容,也可以在幾分鐘內提高整個系統的服務能力。
實時監控體系
11.11大促期間每一分鐘都影響很大,我們需要實時了解線上數據和服務情況,確保系統處于一致和可用的狀態,為此,我們構建了搜索的監控體系。
在索引數據方面,從源頭開始對索引數據準備的各個環節進行驗證,包括數據的條數、處理過程中的異常、最后生成的索引在常見搜索中的執行結果差異等,層層預防,防止有問題的索引數據被用到線上。
在搜索服務方面,監控系統會定時執行常見的搜索,對比排序結果,結果差異較大時及時告警。同時大促期間會有一些商品很快賣完,這些商品繼續顯示在搜索結果中也沒有價值,搜索監控也會及時發現這些商品,觸發索引更新,把商品排到后面。
結語
每年11.11對系統都是一次大閱兵,通過構建分布式搜索引擎,我們實現了基礎架構的可擴展性,結合業務場景設計的Routing規則,保證了搜索的高效執行,自動化工具支持大促必需的自動擴容,配合成體系的驗證和監控,我們有信心應對更高流量的沖擊,保障大促平穩度過。