實時更新索引
1.引子
公司的底層檢索引擎已經用了10年,很穩定也沒有很大的重構需求,直到最近PM報了很多數據更新不及時的問題,
加上最近我也有個想法實現一個輕量級的檢索引擎,於是用了不到2個月算是完成第1版(github地址:https://github.com/dodng/comse)
一是嘗試解決現有公司的檢索系統中更新時效性的問題,二是把自己對檢索服務的理解動手實踐一下。
2.搜索引擎的索引
在我講述索引更新策略前,容我在和大家一起回顧一下搜索引擎的索引,如下:
圖1中藍色的是term,綠色的列表就是倒排索引(不知道的話可以去google搜索),里面的數字代表的是docID
索引的組織結構一般是線性表(docID按照増序排列),方便快速查找(時間復雜度lg(n)),並與別的term索引進行求交(詳見圖2)
3.常見的更新索引策略
現在切入主題,常見的更新索引策略有2個,如下:
1.全量更新后雙buffer交換
優點:查詢快,只是讀取操作,無鎖操作。代碼實現簡單
缺點:內存至少需要索引內存的2倍。索引更新的時效性差。
擴展:我們公司現有的索引就是這個樣子,只不過有2套索引。可以簡單理解為有1套數據量非常大的索引,基本1天更新一次,
另外1套數據量小的索引,半小時更新一次。這2套索引各自更新,最后檢索的結果是這2個索引返回數據的並集,然后再排序輸出。
2.小索引更新后合並到大索引
優點:索引更新的時效性較快
缺點:開發量和代碼實現難度增加,查詢小索引時會有鎖操作
擴展:粗略的看了幾個常用的開源檢索引擎和一些相關的專利,基本都是這種方式。
4."原地"實時更新索引
comse用到的實時更新策略:
1.新增索引
現在的策略比較簡單粗暴,保證索引的docID號是遞增的,新增索引只是在索引后面追加一個docID就好。
2.刪除索引
刪除索引采取的是偽刪除,即用前面一個docID覆蓋要刪除的docID,一是保證了docID是増序排列,二是快速的刪除了docID。
不過有個細節要注意的是每個索引第1個元素要添加一個空元素“0”,保證第1個有用的元素刪除時不會出現異常。
3.壓縮索引
由於刪除元素采用的是偽刪除,會導致索引中堆積大量的重復docID,使用shrink就是壓縮索引,使索引數量最小化,從而達到節省空間
和加快查找速度的目的。