http://www.tuicool.com/articles/NZ7v6b數據庫
阿里集團各大業務快速發展過程當中都對搜索服務不少剛性的須要,而這樣的搜索需求有着很是明顯的特徵:快速支持、低成本、實時性和穩定性。緩存
快速支持:性能優化
業務需求急迫、須要一週甚至幾天內完成索引服務搭建、測試、上線環節。服務器
低成本:架構
搜索需求方要求接入便捷,低成本的機器和運維成本。框架
實時性:運維
搜索需求方的業務數據發生變化,須要實時在索引中進行更新可見,而這個過程一般須要穩定的保證在100ms內。異步
穩定性:分佈式
搜索服務集羣不會由於升級、運維操做或者若干臺機器的宕機致使搜索服務不穩定。oop
阿里的業務基本動輒就是上10億上百億規模,那麼如何能行之有效的管理索引和保障搜索性能將是一個很是具備挑戰性的工做。
互聯網業務負責,那麼涉及到須要進行檢索的源數據可能來自多個數據庫多個表,也就意味着索引數據源可能來源於多庫多表,而且表和表之間還有1:N,N:N的關係。而使用過Lucene的同窗們都知道,對於基於Lucene爲引擎內核的更新都是完整記錄更新,因此對於咱們產品來講構建索引時候避免不了多表join湊整更新問題。
在阿里的衆多搜索需求場景下,不少時候是把搜索服務當作數據庫使用,也就意味着一個頁面上產生的更新操做,頁面跳轉後就能看到最新更新的結果,那麼對於咱們搜索服務來講須要在毫秒級別將更新結果可見。
阿里的業務對穩定性的要求是很是高的,因此對於升級、擴容、機器宕機等狀況都不能影響正常的搜索和更新服務。
電商業務一年下來有很是多的大促活動,而一旦有大促活動,搜索的QPS將會比日常翻幾倍。因此若是以大促的成本去衡量支持服務,整個服務所須要的機器在平時將很是空閒,從而形成了成本極大浪費。那麼針對這種狀況,就須要咱們提供一種靈活的能夠在線伸縮服務吞吐量的技術:即大促前臨時加機器來支持突增的流量,大促後隨時下線擴容機器,而整個過程不影響正常的搜索服務。
由於本文篇幅有限,在這裏我只會着重介紹:實時性、高可用性在咱們產品中的一些技術實踐。
在介紹咱們產品方案以前,首先介紹下業內常見的實時解決方案,見圖1-1實時架構圖:
圖1-1
該方案通常是由:
基於該方案能夠帶來的最大的優點是內存索引能夠合併到主索引,避免了索引碎片,從而能夠屏蔽全量索引從新構建和保障搜索服務的性能穩定性。可是這種方案仍然會存在如下問題:
因此爲了單純追求系統某個指標值(如永遠不須要作全量),而犧牲掉系統穩定性是得不償失的。固然上述某些緣由可能在一些好的硬件配置機器下並不會暴露的特別明顯,可是從技術架構的機器成本上考慮的話,上述設計方案就不是一種特別合適的方案。那麼咱們產品平臺便採起了一種更低成本更穩定的實時架構方案來解決上述問題,其主要思路:
基於上述的思路,我將着重在實時更新處理、實時索引體系兩個方面來跟你們介紹下咱們產品。
大型分佈式系統中故障很常見,設想一下,若是內存索引沒有刷寫,服務器就宕機了。內存中沒有寫於硬盤的數據就會丟失。因此咱們的分佈式實時搜索產品應對的辦法是在寫內存索引以前先寫入WAL(Write-Ahead Logging,預寫式日誌)。其寫入流程以下:
如上所示,在修改內存索引元素以前,要確保與這一個修改相關的操做日誌必需要刷入磁盤中。若是檢索服務器宕機,沒有從RamIndex刷寫入Disk的數據將能夠經過回放WAL來恢復。而這個過程並不須要人爲參與,檢索節點內部機制中有恢復流程來處理。
通常而言搜索系統是須要將WAL日誌刷入磁盤才能夠構建內存索引的,可是若是每一個事務都要求將日誌當即刷入磁盤,系統的吞吐量將會不好。所以,對一致性要求很高的應用,須要當即刷入;相應地,對一致性要求不高的應用,能夠考慮不要求當即刷入,首先將WAL日誌緩存到內存緩存區中,按期刷入磁盤。可是這種作法有一個問題,若是搜索應用系統意外故障,可能丟失最後一部分更新操做。
批提交(Group Commit,如圖1-2批處理流程圖)技術是一種有效的優化手段。WAL日誌首先寫入到系統內容緩存區中:
當知足以上兩個條件中的某一個時,將日誌緩存區中多個事務的操做一次性刷入磁盤,接着一次性將多個事務的修改操做逐個返回客戶端操做結果。批提交技術保證了WAL日誌成功刷入磁盤後,才返回操做結果保障數據的不丟失,雖然犧牲了寫事務延時,但大大提升了系統吞吐量。
圖1-2
考慮數據寫入須要實時可查,那麼更新的數據都是在內存索引中,那麼可能出現一些問題:
故障恢復時須要回放全部WAL,效率較低。若是WAL超過100GB,那麼,故障恢復時間根本沒法接受。另外內存有限,內存索引須要達到閥值後轉儲到磁盤。因此,咱們須要在內存索引轉儲到磁盤的時候,記錄checkpoint時刻的日誌回放點,之後故障恢復只須要回放checkpoint時刻日誌以後的WAL日誌,如圖1-3檢查點方案流程圖所示:
圖1-3
當機器發送重啓,只須要從新加載subindexA、subindexB、subindexC的索引,並重放checkpointC以後的WAL日誌,變可以讓數據恢復到宕機前一致。
圖1-4
根據圖1-4實時方案架構圖咱們詳細說明下實時模式實現流程:
前面咱們說到內存索引一旦達到閥值,將被刷入到磁盤,那麼磁盤將會存在不少相似index_0、index_一、index2,index_3的索引碎片。若是不對這些索引碎片進行合併,那麼隨着這些索引碎片的增長,會致使搜索服務性能下降。因此咱們的產品對索引碎片採起了一種合併策略對其進行按期合併。
圖1-5
如圖1-5子索引合併流程圖所示,內存索引刷入磁盤,將會依次遞增的生成index_0,index_1,index_2的磁盤索引碎片。假設當前的合併因子是2,當合並管理器發現存在2個大小一致索引index_0,index_1的時候,變會觸發合併操做:index_0和index_1合併成index_3,合併過程當中index_0、index_1依然提供正常服務,當合並操做成功完成,即index_3生成完畢,並對外提供服務。接下來將index_0和index_1的資源引用計數減1,即當基於index_0、index1的查詢訪問線程結束時,index_0,index_1的資源引用計數爲0、索引將正常關閉,這樣一個索引碎片合併操做正常結束。可是若是合併過程出現宕機或者異常狀況,即當前合併事務未正常結束,那麼整個合併過程將會回滾,即index_3被清理,index_0,index_1正常提供服務。固然若是內存索引繼續刷到磁盤生成了index_四、index_5,經過合併策略生成了index_6,這個時候發現index_3和index_6又知足了合併條件,那麼index_3和index_6又會合並生成index_7。因此經過這種合併策略,小索引碎片逐步會被合併成大索引碎片,可是若是索引碎片越大,那麼帶來的合併代價也越大,咱們須要設置一個合併閥值,凡是索引碎片達到指定文件大小閥值後,將不會進一步再參與合併,這樣就很好的屏蔽了大索引碎片合併代價過大的問題。
由於前面說到咱們產生索引碎片,而這些索引碎片即便進行了碎片合併而減小碎片數,可是一旦當碎片達到必定大小後就不適合繼續進行合併,不然合併代價很大,因此咱們沒法避免的會由於碎片問題而致使更新實時性和查詢QPS性能損耗問題。因此咱們的解決的辦法就是經過一段時間對具體業務所有源數據進行一次構建全量索引DUMP工做,用構建好的新的全量主索引去替換原來老的主索引和磁盤索引,從而讓實時更新、搜索服務性能恢復到最佳。
阿里的業務數據規模都很龐大,動輒就上10億到百億,那麼咱們若是使用Solr原生的基於檢索服務節點的索引構建模式會帶來2個很大問題:
因此基於上述緣由咱們的搜索平臺實現一個分佈式全量索引任務調度框架來解決搜索業務全量索引構建的問題。
圖1-6
如圖1-6 DUMP中心架構圖所示簡單描述下一個業務全量索引構建的流程:
那麼經過這種離線的分佈式索引構建中心具體爲搜索業務帶來什麼呢,主要在如下幾個方面體現:
咱們產品在solr和Lucene上作了不少優化來適應一些業務的需求,本文篇幅有限,因此在這裏我主要挑出一個比較有表明性的優化實踐:Cache改造。
用過solr的同窗們都知道全部的Cache都是由SolrIndexSearcher來管理的,如圖1-7 Searcher結構圖所示:
圖1-7
而在咱們的實時模式下須要讓更新的數據實時可見,那麼必須近實時的用新的SolrIndexSearcher-new去替換SolrIndexSearcher-old。(如圖1-7)而這樣實時的替換 也就引起以下問題:
因此基於如上的問題,終搜產品從新設計了一些Cache,將Cache的管理由SolrIndexSearcher遷移到IndexReader層中來,如圖1-8 Cache結構圖所示:
圖1-8
首先,先闡述下咱們這種優化思路的前置條件,前文中提到咱們內存索引會直接刷磁盤而不用合併到主索引中,這樣在磁盤存在的主索引、子索引對應的內存視圖對象IndexReader在任什麼時候候都不須要從新打開,而以IndexReader管理的Cache一旦建立後將不會被失效,而須要涉及到預加載Cache的過程只是在刷入磁盤或者系統從新啓動過程當中一次將配置涉及到的Cache都預加載到內存中,那麼以前存在的頻繁失效致使GC、預加載慢引發實時性的若干問題都將不復存在。
因此經過將Cache從Searcher層遷移到IndexReader層的設計使得實時模式下的引擎在複雜的統計查詢下性能也能獲得很好的保證。
本文中咱們深刻的探討了一種高穩定性實時搜索引擎系統實踐,這些實踐內容也依託於咱們的產品服務於阿里衆多業務線。而目前咱們的產品搜索服務集羣已經將近700臺,接入業務範圍也涵蓋整個阿里集團。而這些業務特別是在數據量和訪問量的成倍增加的狀況下,咱們產品更加須要關注
歸根結底其實這些要求是對搜索服務系統的易擴展提出了更高的要求,即如何提供一種無縫的在線擴容方案達到搜索服務吞吐量無上限的目標,而這個目標也正是咱們產品目前正在重點關注的方向,而關於這塊的內容但願有機會在新的文章中跟你們作深刻探討。
柳明(花名:洪震),阿里技術專家,阿里一站式搜索服務平臺TSearcher的負責人。目前關注於分佈式、高性能、高穩定性的搜索服務領域。