FalconEngine - 一個 Go 語言實現的簡單搜索引擎

jopen 9年前發布 | 11K 次閱讀 搜索引擎 FalconEngine
對搜索引擎感興趣的可以去看看 這本書 ,比較淺并且也比較完整的介紹了一個搜索引擎的全部機能。

我的這個搜索引擎原始數據是MySql數據庫的,大家可以根據需要進行二次開發,用來支持其他數據庫或者本地文件,Detail文件是存儲在 Redis數據庫中,同樣這部分也可以根據自己的需要二次開發,使用本地文件或者其他數據庫,倒排索引和正排索引本地存儲的時候使用的json格式,比較耗磁盤,第一版暫時這樣了吧,后續再做優化。

性能測試

  • 不好意思,還沒測呢,功能已經都測完了,性能還未優化,后續會測試,這是個持續的項目,會一直優化下去。

使用方法

依賴以下幾個庫

  • 直接運行install.sh
  • github.com/huichen/sego 獲取分詞的字典文件
  • 運行索引器,會將索引文件生成到index目錄下

bin/FalconEngine -mode=build

  • 運行搜索器

bin/FalconEngine -mode=search

基本概念

以下幾個概念需要理解,如果完全不了解的話,還需要自己稍微百度一下:倒排索引,正排文件,Detail文件,全量索引,增量索引,哈希函數,DocId

基礎數據結構

搜索引擎首先并不神秘,基礎的數據結構就那么幾個,定了以后后面就是在上面添磚加瓦了。

假如有下面五個文檔需要進行搜索

文檔編號 內容
1 你好,搜索引擎
2 搜索引擎有一條數據
3 你好,有一條測試數據

倒排索引

倒排索引是搜索引擎基礎中的基礎,主要的檢索都是從倒排索引開始的,所以,首先,設計一個倒排索引的數據結構是所有搜索引擎的基礎。

搜索引擎的基礎是DocId,也就是文檔ID,DocId是唯一的并且是連續的,而倒排索引就是一組DocId鏈表,每個鏈表對應一個關鍵詞。

上面的文檔建立號倒排索引的基礎結構如下圖

關鍵詞 文檔編號
你好 1,3
搜索引擎 1,2
數據 2,3
有一條 2,3
測試 3

所以,當我們檢索數據這個詞的時候能迅速知道在文檔 23 有這條數據,就能進行檢索了。

是不是很簡單,關鍵問題是檢索數據的時候,如何能迅速定位到第三行數據,這里就用到哈希表了,所以,一個完整的倒排包括兩部分,一部分是上面的這個表,第二個是一個哈希表,通過這個哈希表能知道數據這個詞的下標為3,從而找到2,3這兩個文檔。

哈希表的具體實現就不詳細展開了,哈希表有很多種實現方式,并且哈希函數也有很多種實現方式,總之,對于一個關鍵詞的定位

  • 首先,通過計算這個關鍵詞的hash,得到它的下標
  • 然后,查找倒排索引的下標,得到文檔ID的鏈表

在代碼的InvertIndex.go中是倒排索引的數據結構,StringIndexDic.go是關鍵詞的哈希表,這兩個文件產生的數據都會序列化成json文件存儲下來。

正排索引

正排索引相對倒排就簡單多了,實際上就是一個字典文件,key是DocId,value是這個DocId對應的內容,主要用來做結果集的過濾,所謂倒排檢索,正排過濾,什么場景需要這樣的東西呢?下面的場景你肯定經歷過。

你在一個某東的網站搜索運動鞋,肯定出來一堆鞋子,但是你只想看nike的鞋子,這時候你可以再運動鞋后面加上Nike,搜索nike運動鞋,但是結果不一定準,因為并不是每個nike的鞋子的標題上都會寫上nike,這時候就需要用到正排了,他會把nike鞋子給你過濾出來。

正排索引就是一個數組,數組的下標就是DocId,文件中的NumberProfile.go和TextProfile.go是具體的實現文件

Detail文件

Detail文件使用的是Redis實現的,沒有具體的數據結構,實際上就是以主鍵ID為key來實現的。

增量更新

增量更新使用的是掃描mysql中的一個last_modify_time字段,獲取數據,然后和redis中的數據進行對比,如果更新了就添加到索引中,添加索引按照如下的步驟進行

  • 如果是正排字段更新,并且不是新增的數據,只是原來的數據修改

    • 直接更新DocId對應下標的數據
  • 如果是正排字段更新,但是是新增的數據

    • 新增一個DocId并添加到正排文件的后面
  • 如果是倒排字段更新

    • 將原始的DocId從BitMap中刪除
    • 新增一個DocId并添加到倒排文件的后面

因為DocId是連續的,倒排字段更新的話,要修改倒排鏈表,而目前的倒排鏈表是數組的,所以直接建立一個BitMap,將對應的DocId刪除,后續改成鏈表形式的話,可以動態的刪除。

增量更新使用的一個go的協程來做的,掃描的是數據庫字段,后續可以改成從kafka獲取數據或者其他方式獲取增量更新

數據檢索

數據檢索分成以下幾個步驟

  • 根據關鍵詞從倒排索引中獲取DocId鏈,有多個關鍵詞的時候求交集
  • 通過BitMap過濾掉已經刪除的DocId
  • 最后得到的DocId按照正排文件的條件進行過濾操作,獲取最終的DocId鏈
  • 通過DocId反查出文檔的真實ID,并通過Redis獲取文檔的詳細信息用于顯示

文件中的IndexSet.go主要實現了上述步驟

項目地址是: https://github.com/wyh267/FalconEngine

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!