一、反向索引
-
反向索引
詞項(term) : 搜尋時的一個機關,代表文本中某個詞
反向索引結果是一種将詞項映射得到文檔的資料結構
-
反向索引建立步驟
a. 提取詞項
首先對文檔分詞,英文文檔用空格分隔
去除無實際意義的詞,如is、a、in、as等
對單詞統一大小寫
單複數,過去式、進行時轉換
過濾标點符号
【本步驟,将無用的過濾掉并統一詞項格式】
b. 建立反向索引
将詞項映射到文檔
【将提取的詞項,映射到文檔,一個詞項可對應多個文檔】
c. 建立詞項出現的頻率、位置和偏移量
文檔ID:用于根據詞項定位文檔的原始資訊
頻率:記錄詞項在文檔出現的次數,用于搜尋相關性算分
位置:記錄在文檔中是第幾個關鍵字,用于詞組查詢
偏移量:記錄開始和結束的位置,用于做高亮顯示
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL1MjMzQDMzYTMzEDOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
二、 底層内部原理
-
反向索引不可變性
反向索引寫進磁盤永不會被改變
- 是以無需鎖,不必擔心多程序同時修改資料問題
- 大部分讀請求直接請求記憶體,不命中磁盤
- 不會因為資料改變而重建緩存中資料
- 單個大的反向索引允許資料被壓縮
- 不支援部分文檔更新
- 新文檔可被搜尋,需重建整個反向索引,限制索引包含資料量,索引更新頻率
- Lucene按段搜尋(per-segment)
- 段檔案(segment file):存儲反向索引的檔案,每個segment是一個反向索引。文檔寫入lucene,并且生成完整的segment後才能被搜尋
- 送出點(Commit point):記錄所有已知段的檔案
- 事務日志(translog):防止es當機導緻資料丢失,es每次寫入資料同時寫入translog。
ps:在反向索引的不可變前提下,實作反向索引的資料增删改
- 使用更多索引,按段搜尋
- 一個lucene索引包含:segment的集合、Commit point檔案
- 按segment搜尋,每個segment是一個反向索引,通過增加新的索引反應最近的修改,而不重寫整個反向索引,當有資料查詢請求,每個反向索引都被周遊,從最早的開始,查詢完後對結果合并。
- 實作按段搜尋,索引工作流程
-
- 當新文檔被索引時,先收集到記憶體緩存
-
- (送出緩存)将緩存中對象轉換為segment存儲到磁盤,在Commit point 記錄新段資訊
-
- (開啟新段)新的段被open,此時新段包含的文檔可被搜尋
-
- 清空記憶體緩存資料,等接受新文檔
- 文檔的删除和更新
-
- 每個Commit point 包含一個.del檔案,該檔案會列出這些被删除文檔的段資訊
-
- 當一個文檔被删時,實際隻在.del檔案中被标記删除,被标記删除的文檔依然可被查詢得到,但在最終結果被傳回前從結果集中删除
-
- 當一個文檔更新時,舊文檔被标記删除,新文檔被索引到一個新的段,兩個文檔可能被一個查詢比對到,但在結果傳回前會在結果集中删除
- ps:段合并後,标記删除的文檔會移除
- 查詢流程
-
- 查詢被觸發
-
- 從Commit point 擷取已知段資訊,按順序查詢所有段
-
- 聚合所有段的查詢結果
-
- 較小成本實作新文檔添加到索引
- 按段搜尋的問題
-
- 每次commit一個新segment,需将資料fsync到實體磁盤,fsync代價大,每次索引一個文檔就fsync一次,代價很大
- 近實時
- 為解決按segment搜尋的問題,先将寫入内容緩存的lucene資料轉換為segment存入檔案系統緩存,等合适時機再将檔案系統緩存中的資料送出,fsync到磁盤持久化
-
- 先将文檔寫入記憶體緩存
-
- 将記憶體緩存中資料轉為segment,存入檔案系統緩存,重新reopen,該過程是refresh(一般1秒refresh一次)
-
- 等合适時機,将檔案系統緩存中資料送出,fsync到磁盤持久化
- 引入檔案系統緩存的遺留問題
-
- 沒flush到磁盤的資料,若發生斷電、當機,緩存資料會丢失
- 斷電、當機資料不丢失
- es引入translog子產品,将将資料同時寫入記憶體緩存(lucene)和translog,資料發生丢失時,可從translog重新将資料恢複
- es索引資料完整流程
-
- 寫lucene和translog
- 當索引文檔(寫資料時),先将文檔寫入lucene,此時lucene在記憶體中,然後寫translog,寫成功後将請求發給使用者
-
- 使搜尋可見
- 将記憶體中對象轉為segment,再reopen,該操作為refresh
-
- 刷Translog日志
- 将記憶體中的translog刷到磁盤,預設5秒一次
-
- 執行lucene送出(flush)
- 将記憶體中segment刷到磁盤,更新commit point,清空translog,打開新的translog,預設translog達到512M,flush一次
- 段合并
- 自動refresh,每秒會建立一個新的segment,不加處理會導緻搜尋變慢
- 段合并流程
-
- 合并程序選一部分大小相似的segment,在背景 合并到更大的segment,不會中斷索引和搜尋
-
- 合并結束後,老segment被删,新segment被flush到磁盤,寫入一個包含新segment且排除舊的和較小的segment,新的commit point
-
- 新的segment被用來搜尋,老的segment被删