【恩墨學院】百度如何能實時檢索到15分鐘前新生成的網頁(下)

恩墨學院發表於2017-11-06

編輯手記:

百度為何能實時檢索出15分鐘之前新出的新聞?58同城為何能實時檢索出1秒鐘之前釋出的帖子?我們揀選架構師之路中的一個系列文章,體系化的聊聊搜尋引擎,從宏觀到細節,詳解實時檢索的原理。只要業務有檢索需求,本文一定對你有幫助。


本文重點介紹:

一、流量資料量由小到大,常見搜尋方案與架構變遷

二、資料量、併發量、擴充套件性方案

三、搜尋引擎的實時性架構

1檢索需求的滿足與架構演進


任何網際網路需求,或多或少有檢索需求,還是以58同城的帖子業務場景為例。

帖子的標題,帖子的內容有很強的使用者檢索需求,在業務、流量、併發量逐步遞增的各個階段,應該如何實現檢索需求呢?

那麼為了滿足搜尋業務的需求,隨著資料量和併發量的增長,搜尋架構一般會經歷這麼幾個階段:

1)原始階段-LIKE

2)初級階段-全文索引

3)中級階段-開源外接索引

4)高階階段-自研搜尋引擎

原始階段-LIKE

資料在資料庫中可能是這麼儲存的:

t_tiezi(tid, title, content)

滿足標題、內容的檢索需求可以透過LIKE實現:

select tid from t_tiezi where content like ‘%天通苑%


能夠快速滿足業務需求,存在的問題也顯而易見:

1)效率低,每次需要全表掃描,計算量大,併發高時cpu容易100%

2)不支援分詞


初級階段-全文索引

如何快速提高效率,支援分詞,並對原有系統架構影響儘可能小呢,第一時間想到的是建立全文索引:

alter table t_tiezi add fulltext(title,content)

使用matchagainst實現索引欄位上的查詢需求。


全文索引能夠快速實現業務上分詞的需求,並且快速提升效能(分詞後倒排,至少不要全表掃描了),但也存在一些問題

1)只適用於MyISAM

2)由於全文索引利用的是資料庫特性,搜尋需求和普通CURD需求耦合在資料庫中:檢索需求併發大時,可能影響CURD的請求;CURD併發大時,檢索會非常的慢;

3)資料量達到百萬級別,效能還是會顯著降低,查詢返回時間很長,業務難以接受

4)比較難水平擴充套件


中級階段-開源外接索引

為了解決全文索引的侷限性,當資料量增加到大幾百萬,千萬級別時,就要考慮外接索引了。


外接索引的核心思路:索引資料與原始資料分離,前者滿足搜尋需求,後者滿足CURD需求,透過一定的機制(雙寫,通知,定期重建)來保證資料的一致性。


原始資料可以繼續使用Mysql來儲存,外接索引如何實施?

Solr,LuceneES都是常見的開源方案。強烈推薦ESElasticSearch


Lucene雖好,但始終有一些不足

1Lucene只是一個庫,潛臺詞是,需要自己做服務,自己實現高可用/可擴充套件/負載均衡等複雜特性

2Lucene只支援Java,如果要支援其他語言,還是得自己做服務

3Lucene不友好,這是很致命的,非常複雜,使用者往往需要深入瞭解搜尋的知識來理解它的工作原理,為了遮蔽其複雜性,一個辦法是自己做服務


為了改善Lucene的各項不足,解決方案都是“封裝一個介面友好的服務,遮蔽底層複雜性”,於是有了ES


1ES是一個以Lucene為核心來實現搜尋功能,提供REStful介面的服務

2ES能夠支援很大資料量的資訊儲存,支援很高併發的搜尋請求

3ES支援叢集,向使用者遮蔽高可用/可擴充套件/負載均衡等複雜特性


目前58到家使用ES作為核心,實現了自己的搜尋服務平臺,能夠透過在平臺上簡單的配置,實現業務方的搜尋需求。

搜尋服務資料量最大的“介面耗時資料收集”需求,資料量大概在7億左右;併發量最大的“經緯度,地理位置搜尋”需求,線上平均併發量大概在600左右,壓測資料併發量在6000左右。



ES完全能滿足10億資料量,5k吞吐量的常見搜尋業務需求,強烈推薦。


高階階段-自研搜尋引擎

當資料量進一步增加,達到10億、100億資料量;併發量也進一步增加,達到每秒10萬吞吐;業務個性也逐步增加的時候,就需要自研搜尋引擎了,定製化實現搜尋核心了。


2

資料量、併發量、擴充套件性方案


到了定製化自研搜尋引擎的階段,超大資料量、超高併發量為設計重點,為了達到“無限容量、無限併發”的需求,架構設計需要重點考慮“擴充套件性”,力爭做到:增加機器就能擴容(資料量+併發量)。


58同城的自研搜尋引擎E-search初步架構圖如下:


 
恩墨學院-專注oracle大資料培訓

1)上層proxy(粉色)是接入叢集:

為對外門戶,接受搜尋請求,其無狀態效能夠保證增加機器就能擴充proxy叢集效能

2)中層merger(淺藍色)是邏輯叢集

主要用於實現搜尋合併,以及打分排序,業務相關的rank就在這一層實現,其無狀態性也能夠保證增加機器就能擴充merger叢集效能

3)底層searcher(暗紅色大框)是檢索叢集:

服務和索引資料部署在同一臺機器上,服務啟動時可以載入索引資料到記憶體,請求訪問時從記憶體中load資料,訪問速度很快

①為了滿足資料容量的擴充套件性,索引資料進行了水平切分,增加切分份數,就能夠無限擴充套件效能,如上圖searcher分為了4

②為了滿足一份資料的效能擴充套件性,同一份資料進行了冗餘,理論上做到增加機器就無限擴充套件效能,如上圖每組searcher又冗餘了2


如此設計,真正做到做:

增加機器就能承載更多的資料量,響應更高的併發量



3

實時搜尋引擎架構


大資料量、高併發量情況下的搜尋引擎為了保證實時性,架構設計上的兩個要點:

1)索引分級

2dump&merge;


索引分級

《深入淺出搜尋架構(上篇)》介紹了搜尋引擎的底層原理,在資料量非常大的情況下,為了保證倒排索引的高效檢索效率,任何對資料的更新,並不會實時修改索引,一旦產生碎片,會大大降低檢索效率。


既然索引資料不能實時修改,如何保證最新的網頁能夠被索引到呢?

索引分為全量庫、日增量庫、小時增量庫


如下圖所述:

1300億資料在全量索引庫中

210001天內修改過的資料在天庫中

3501小時內修改過的資料在小時庫中


恩墨學院-專注oracle大資料培訓



當有修改請求發生時,只會操作最低階別的索引,例如小時庫。


恩墨學院-專注oracle大資料培訓

當有查詢請求發生時,會同時查詢各個級別的索引,將結果合併,得到最新的資料:

1)全量庫是緊密儲存的索引,無碎片,速度快

2)天庫是緊密儲存,速度快

3)小時庫資料量小,速度也快


資料的寫入和讀取都是實時的,所以58同城能夠檢索到1秒鐘之前釋出的帖子,即使全量庫有300億的資料。


新的問題來了:小時庫資料何時反映到天庫中,天庫中的資料何時反映到全量庫中呢?


dump&merge;

這是由兩個非同步的工具完成的:


恩墨學院-專注oracle大資料培訓

dumper:將線上的資料匯出

merger:將離線的資料合併到高一級別的索引中去


小時庫,一小時一次,合併到天庫中去;

天庫,一天一次,合併到全量庫中去;

這樣就保證了小時庫和天庫的資料量都不會特別大;

如果資料量和併發量更大,還能增加星期庫,月庫來緩衝。


4

總結


超大資料量,超高併發量,實時搜尋引擎的兩個架構要點:

1)索引分級

2dump&merge;

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28530558/viewspace-2146869/,如需轉載,請註明出處,否則將追究法律責任。

相關文章