随着公司業務的高速發展以及資料爆炸式的增長,目前公司各産線都有關于搜尋方面的需求,但是以前的搜尋服務系統由于架構與業務上的設計,不能很好的滿足各個業務線的期望,主要展現下面三個問題:
不能支援對語句級别的搜尋,大量業務相關的屬性根本無法實作
沒有任何搜尋相關的名額評價體系
擴充性與維護性特别差
基于現狀,對行業内的搜尋服務做出充分調研,确認使用ElasticSearch做底層索引存儲,同時重新設計現有搜尋服務,使其滿足業務方對維護性、定制化搜尋排序方面的需求。
滬江搜尋服務底層基于分布式搜尋引擎ElasticSearch,ElasticSearch是一個基于Lucene建構的開源,分布式,Restful搜尋引擎;能夠達到近實時搜尋,穩定,可靠,快速響應的要求。

搜尋服務整體分為5個子系統
搜尋服務(Search Server) : 提供搜尋與查詢的功能
更新服務(Index Server) : 提供增量更新與全量更新的功能
Admin 控制台 : 提供UI界面,友善索引相關的維護操作
ElasticSearch存儲系統 : 底層索引資料存儲服務
監控平台: 提供基于ELK日志與zabbix的監控
查詢
查詢接口提供http的調用方式,當出現跨機房通路的時候,請使用http接口,其餘都可以使用dubbo RPC調用
增量更新
資料增量更新接口采用提供MQ的方式接入。當業務方出現資料更新的時候,隻需将資料推送到對應的MQ通道中即可。更新服務會監聽每個業務方通道,及時将資料更新到ElasticSearch中
全量索引
更新服務會調用業務方提供的全量Http接口(該接口需提供分頁查詢等功能)
衆所周知,全量更新的功能在搜尋服務中是必不可少的一環。它主要能解決以下三個問題
業務方本身系統的故障,出現大量資料的丢失
業務高速發展産生增減字段或者修改分詞算法等相關的需求
業務冷啟動會有一次性導入大批量資料的需求
基于上面提到的問題,我們與業務方合作實作了全量索引。但是在這個過程中,我們也發現一個通用的問題。在進行全量更新的時候,其實增量更新也在同時進行,如果這兩種更新同時在進行的話,就會有遇到少量增量更新的資料丢失。比如說下面這個場景
業務方發現自己搜尋業務alias_A資料大量資料丢失,是以進行索引重建。其中alias_A是别名,就是我們通常說alias,但是底層真正的索引是index_201701011200(建議:索引裡面包含時間屬性,這樣就能知道是什麼建立的)
首先建立一個新的索引index_201706011200,然後從資料中拉出資料并插入ES中,并記錄時間戳T1,最後索引完成的時間戳為T2,并切換搜尋别名index_1指向index_201706011200。
索引建立成功之後的最新資料為T1這個時刻的,但是T1到T2這段時間的資料,并沒有擷取出來。同時index_201701011200老索引還在繼續消費MQ中的資料,包括T1到T2時間内的缺少資料。
是以每次索引重建的時候,都會缺少T1到T2時間内的資料。
最後,針對上面這個場景,我們提出通過zookeeper分布式鎖來暫停index consumer的消費,具體步驟如下
建立new_index
擷取該index 對應的别名,來修改分布式鎖的狀态為stop
index consumer監控stop狀态,暫停索引資料的更新
new_index索引資料建立完畢,更新分布式鎖狀态為start
index consumer監控start狀态,繼續索引資料的更新
這樣的話,我們就不用擔心在建立索引的這段時間内,資料會有缺少的問題。相信大家對于這種方式解決全量與增量更新資料有所體會。
資料量爆炸式的增加,導緻我們ES叢集最終還是遇到了容量不足的問題。在此背景下,同時結合ES本身提供的無縫擴容功能,我們最終決定對線上ES叢集進行了線上的無縫擴容,将從原來的3台機器擴容為5台,具體步驟如下
擴容前準備
目前我們線上已經有3台機器正在運作着,其中node1為master節點,node2和node3為data節點,節點通信采用單點傳播的形式而非廣播的方式。
準備2台(node4與node5)機器,其中機器本身配置與ES配置參數需保持一緻
擴容中增加節點
啟動node4與node5(注意一個一個啟動),啟動完成之後,檢視node1,2,3,4,5節點狀态,正常情況下node1,2,3節點都已發現node4與node5,并且各節點之間狀态應該是一緻的
重新開機master node
修改node1,2,3節點配置與node4,5保持一緻,然後順序重新開機node2與node3,一定要優先重新開機data node,最後我們在重新開機node1(master node).到此為止,我們的線上ES叢集就線上無縫的擴容完畢
查詢與更新服務分離
查詢服務與更新服務在部署上進行實體隔離,這樣可以隔離更新服務的不穩定對查詢服務的影響
預留一半記憶體
ES底層存儲引擎是基于Lucene,Lucenede的反向索引是先在記憶體中生成,然後定期以段的形式異步重新整理到磁盤上,同時作業系統也會把這些段檔案緩存起來,以便更快的通路。是以Lucene的性能取決于和OS的互動,如果你把所有的記憶體都配置設定給Elasticsearch,不留一點給Lucene,那你的全文檢索性能會很差的。所有官方建議,預留一半以上記憶體給Lucene使用
記憶體不要超過32G
盡量避免使用wildcard
其實使用wildcard查詢,有點類似于在資料庫中使用左右通配符查詢。(如:*foo*z這樣的形式)
設定合理的重新整理時間
ES中預設index.refresh_interval參數為1s。對于大多數搜尋場景來說,資料生效時間不需要這麼及時,是以大家可以根據自己業務的容忍程度來調整
本章主要介紹公司搜尋服務的整體架構,重點對全量更新中資料一緻性的問題,ES線上擴容做了一定的闡述,同時列舉了一些公司在部署ES上做的一些優化。本文主要目的,希望大家通過閱讀滬江搜尋實踐,能夠給廣大讀者帶來一些關于搭建一套通用搜尋的建議。