根據某位和我同姓的朋友的建議,後面的文章都會加上副標題,方便查閱。算法
今天的文章會比較短,很快就能看完。數據庫
按照步驟,說完段層之後,應該就開始涉及到索引層了,但我想說的是一個分佈式的搜索引擎,因此除了索引層之外,還有個分片層,這兩個概念是緊密聯繫在一塊兒的,我怕說很差,因此在說索引層和分片層以前,咱們先直觀的對索引有個瞭解,而且先熟悉一下索引層的一些特殊的數據結構以及一些經常使用算法,讓你們對搜索引擎有個總體瞭解之後再來講說索引層和分片層。數組
本篇只會涉及到數據的增,刪,改,由於查是一個大的話題,涉及的東西有點多,可能須要單獨的一篇甚至兩篇來講,好了,不廢話,咱們來講說今天的主題吧。數據結構
以前咱們已經基本將搜索引擎的底層數據結構介紹完畢了,那麼一個搜索引擎最基本的功能也和數據庫同樣,爲了使搜索引擎跑起來,必需要有增,刪,改,查四個基本功能,下來咱們一個一個來講。分佈式
在這以前,咱們還須要一些準備工做,那麼仍是用一個例子引出全部內容,假如咱們有一份這樣的微博數據,每一條數據就是一個微博用戶發佈的一條微博,每條數據有三個字段,分別是用戶暱稱,微博內容,發佈時間,具體數據長成這樣子:搜索引擎
{"nickname":"吳YH堅","content":"今天是個好日子","datetime":"2016-05-05 22:12:00"}3d
那麼首先,咱們須要創建一個這樣的索引結構cdn
字段名稱 | 字段類型 |
---|---|
nickname | string(全詞匹配) 倒排+正排 |
content | string(分詞模式匹配) 倒排+正排 |
datetime | datetime(時間類型) 正排 |
_id | 主鍵(自動生成型主鍵) 倒排+正排 |
好了,把上面這個表的內容提交到搜索引擎中,就創建好這個索引結構了,搜索引擎會按照咱們以前所寫的,創建好各個字段,給每一個字段創建好倒排和正排索引
增這個其實就是全量索引構建和增量索引構建了,咱們以前一直再說的就是這個,這裏咱們就不詳細說了。內存
不論是全量仍是增量,增長數據的時候就是將一條一條上文中的原始數據導入到搜索引擎中,每增長一條數據會先在內存中增長數據,而後達到必定條件之後將一批數據寫入到段文件中,而且達到必定條件之後會將各個段合併起來。
惟一要說的是主鍵這個字段,因爲在原始數據中是沒有_id這個東西的,因此在增長數據的時候搜索引擎內部會給每條數據生成一個_id。
具體的_id的生成方法有不少,可使用隨機數生成,也可使用GUID的方法進行生成,只要保證_id的惟一性就好了,因爲最後咱們須要的是一個分佈式的搜索引擎,因此_id的生成方法仍是有一些講究的,通常簡單的能夠用隨機數-時間戳-本機IP(MAC)地址來生成,這樣產生相同的_id機率就已經幾乎沒有了,固然對於分佈式系統還有其餘辦法生成惟一_id,咱們之後會介紹。
主鍵的倒排我沒有保存在段中,而是直接使用了一個叫primary.pk的B+樹文件進行保存,這個B+樹的value就是主鍵對應的docid,由於主鍵是惟一的,因此只須要一個value值就好了,不須要倒排鏈。
若是數據中自帶惟一id,那麼更簡單,直接使用就好了。
通常搜索引擎也提供無主鍵的數據檢索,這種索引就只有增長和檢索操做了,因爲沒有主鍵,通常不提供刪除和修改操做。
刪除操做是搜索引擎比較特殊的操做,由於咱們知道,保存到搜索引擎中的數據有倒排文件,想一想倒排文件的數據結構,要從中刪除一個文檔的話,須要先找出這個文檔的內容,而後找到全部包含這個文檔的倒排鏈,而後把每一個倒排鏈中的文檔刪除掉,再把倒排鏈重新排列,寫入倒排文件中,加上讀取詞典數據,少說也有6,7次IO。
很麻煩是否是,咱們固然不會這麼作,這裏,咱們用到了一個新的數據結構,bitmap,分分鐘解決問題。
bitmap是什麼?bitmap是一種很是高效和經常使用的數據結構,它經過一個bit數組來存儲特定數據的一種數據結構;因爲bit是數據的最小單位,因此這種數據結構每每是很是節省存儲空間,而一個bit要不是0,要不是1,因此bitmap只適合用來存儲ture/false的這種數據(擴展之後能夠存儲更多信息),好比下面就是一個32位的bitmap,它能夠用來表示0到31這些數中,哪些是有效的(用0表示),哪些是無效的(用1表示),在這裏,0,4,14這三個數是無效的。這個數據結構很好理解吧。
0000 0000 0000 0000 0100 0000 0001 0001
而搜索引擎中,docid是連續的,而且docid是有效的仍是被刪除了正好對應ture和false,因此很是適合使用bitmap來描述某個文檔是否被刪除。
bitmap的基本運算是位運算,因此速度也特別快,而且bitmap用一個bit來表示一個文檔,因此存儲空間也很是少,一個16M的bitmap能夠存儲134217728個文檔是否被刪除的信息。
因此,在搜索引擎中刪除一個數據,咱們按照如下幾步進行
因此說是刪除,實際並無刪除,數據還在,在檢索的時候作點小動做就能讓人以爲被刪除了,什麼小動做說檢索的時候再說吧。
有了增和刪,改的話就簡單了,先刪再增就是改了。
改的話還有個小技巧,爲了儘可能的少增長數據量,當咱們修改的時候若是隻修改了正排字段,而且修改先後正排字段的長度沒有發生變化的話,咱們能夠直接在原始的記錄上覆蓋,而不用刪除再增長記錄,固然,這麼作的話,修改的時候須要比對全部字段來判斷使用哪一種更新模式,不如先刪後增來得直接,並且在分佈式的環境下,這樣不太利於同步數據。
說完了增,刪,改,特別特別簡單吧,但咱們發現搜索引擎若是一直不停的修改刪除數據的話,而實際上並無真正的刪除數據,數據會愈來愈多並不會減小,因此搜索引擎每隔一段時間都要重作一下全量索引,把無用的數據真正的清除掉,否則冗餘的數據愈來愈多,會影響查詢的效率。
後面一篇咱們再來詳細說說查,涉及到的算法部分稍微多一點,一篇可能說不完。
若是想看其餘文章,歡迎關注個人公衆號,主要聊聊搜索引擎,推薦廣告算法以及其餘瞎扯的東西 :)