從零開始,寫一個搜尋引擎 (0x01)
第零部分我們已經列了一個提綱了,這一篇文章開始要詳細說說了。
搜尋引擎基本概念
在說搜尋引擎架構分層之前,我們先確定幾個搜尋引擎的概念。
文件
,搜尋引擎的基本資料單元,比如一張網頁,一個商品,多個文件合在一起就是一個搜尋引擎的完整資料倒排索引
,正排索引
,儲存在搜尋引擎內部的資料結構,也是搜尋引擎最底層的資料結構。索引器
,將文件
資料生成可供搜尋的倒排索引
和正排索引
的程式就是索引器。檢索器
,通過對倒排索引
和正排索引
進行查詢,從而查詢到文件
的程式。欄位
,每個文件可能有多個欄位,比如一篇文章有標題,作者,摘要,詳情,釋出時間的,這些東西雖然在一個文件
中,但是搜尋的時候需要區別對待。索引
,多個文件
通過索引器
生成了一堆倒排正排索引,我們把這些倒排正排索引的集合叫索引
,如果後面提到索引
就是指正排和倒排索引的集合,索引也可以理解為資料庫中的表。
好了,上面就是搜尋引擎的最基本的概念,搜尋引擎簡單的說分成兩部分,一部分就是索引器
把文件變成倒排
和正排
檔案,第二部分就是檢索器
通過倒排
和正排
檔案還原文件
的過程。
搜尋引擎設計分層
資料庫其實也是一個搜尋引擎,只是資料庫和搜尋引擎的側重點不太一樣,搜尋引擎追求的是簡單,速度快,而資料庫追求的是穩定和複雜邏輯對資料的處理,所以應用場景不太一樣。
既然知道了一個搜尋引擎的基本概念,應該怎麼來設計這個搜尋引擎呢?
按照一般的軟體設計邏輯,如果不是非常複雜的系統,要設計一個系統,首先要設計資料結構,然後把資料結構封裝到各個演算法和類中,然後將各個類組合起來就完成了,所以,我設計這個引擎,是基於以下幾個層次來的。
- 首先需要一個底層的資料層,用來儲存
倒排索引
和正排索引
,每個欄位都會建立相應的倒排和正排索引,這一部分應該有一系列相關的模組來實現; - 所有欄位的
倒排索引
和正排索引
合起來就是整個資料檔案,然後需要一些模組來對這些東西進行管理; - 然後由於在第一篇文章中我們說了希望
索引器
和檢索器
都在這裡,類似ElasticSearch
的實現,所以也使用了分段的方式管理文件的索引
,每到一定的條件下將索引
重新整理到磁碟或者將索引合併起來。 - 我們還需要一個引擎的東西來管理多個
索引
,引擎負責複雜的查詢策略和排序策略,這個引擎是可以更換和修改了,只需要實現標準介面就行,也可以自己實現來替換預設的引擎達到更多的功能,甚至你能自己寫一個引擎,實現SQL查詢。 - 最後還需要一個和外界互動的層,我實現的是一個http伺服器來和外部互動,互動的資料通過
json
來進行,這一層也可以重寫成任何你需要的樣子。
按照上面這些個模組,一個搜尋引擎,在整體架構上大約分成以下幾個層次
- 首先,最底層的是資料模組層,負責引擎內所有的資料描述,對於搜尋引擎來說,資料分為
倒排索引
和正排索引
,也叫逆向索引
和正向索引
,為了方便,我們這統一叫倒排索引
和正排索引
。 - 在這一層之上是欄位層,每一個欄位對應了一個正排索引和一個倒排索引(可選),因為有些欄位只需要展示出來而不需要進行搜尋是不需要倒排的。
- 在欄位層之前有個段的層來對這些欄位進行管理,段有的在記憶體中,有的重新整理到磁碟上了。
- 段層之上就是索引模組層了,這一層對上提供一些基本的增加,刪除,修改,查詢的介面。
- 索引模組層之上是引擎層,這一層實現具體的業務查詢邏輯。
- 最上面是一個網路層,負責和外界進行互動。
在實現的時候,為了儘量簡單,每個模組基本上都是一個檔案來實現的,用了Golang
以後,程式碼寫起來也自由起來了,只要清晰就行,所以整個引擎下來,程式碼量其實不是很大。
下面這個圖就是整個程式碼的大框架圖,後面我們會一個一個的來講這些東西。
通過這一篇文章,希望能對搜尋引擎有個初步的瞭解了,後面我會一個一個模組一個一個技術點的來拆分一下這個搜尋引擎。
接下來的文章會開始介紹搜尋引擎的底層技術了,倒排索引【會花比較多精力來說倒排索引,畢竟這是核心的核心】,正排索引【這個簡單,就是陣列】,在介紹的時候會有幾篇文章介紹實現倒排索引技術需要的一些演算法和資料結構。
程式碼託管在github
上,地址是github.com/wyh267/Falc…,程式碼還在不斷更新中,目前程式碼量,去掉單元測試檔案,大約是6000行,因為是想到哪寫到哪,有些函式也沒有用,所以還有優化空間,也希望大家提交你的patch,後面講的時候可以對照程式碼看看。
程式碼結構如下,再說一遍,程式碼量不大,結構也非常簡單,雖然我寫的程式碼註釋不多,但是沒有使用任何高階功能,閉包都沒有,直接看沒任何難度。
歡迎大家掃描一下下面的微信公眾號訂閱,首先會在這裡發出來:)