有道雲排版好一點:https://note.youdao.com/ynoteshare1/index.html?id=a38978147bd85dd15148027aeadd1c92&type=note
倒排索引存儲了比包含了一個特定term的文檔列表多地多的信息。它可能存儲包含每個term的文檔數量,一個term出現在指定文檔中的頻次,每個文檔中term的順序,每個文檔的長
度,所有文檔的平均長度,等等。這些統計信息讓Elasticsearch知道哪些term更重要,哪些
文檔更重要,也就是相關性。
1.不可變性
寫入磁盤的倒排索引是不可變的,它有如下好處:
1.不需要鎖。如果從來不需要更新一個索引,就不必擔心多個程序同時嘗試修改。
2.一旦索引被讀入文件系統的緩存(譯者:在內存),它就一直在那兒,因爲不會改變。只要文件系統緩存有足夠的空間,大部分的讀會直接訪問內存而不是磁盤。這有助於性能提升。
3.在索引的聲明週期內,所有的其他緩存都可用。它們不需要在每次數據變化了都重建,因爲數據不會變。
4.寫入單個大的倒排索引,可以壓縮數據,較少磁盤IO和需要緩存索引的內存大小。
此處的不可變可以理解爲已寫入的索引不會局部變化,只會不斷累加或者重寫。有點類似redis持久化裏面的aof,不斷累加日誌,然後到一定量之後經行“重寫”。
2.動態索引
既然要不可變,那麼更新的話只能選擇多個索引。不是重寫整個倒排索引,而是增加額外的索引反映最近的變化。每個倒排索引都可以按順序查詢,從最老的開始,最後把結果聚合。有點像累加,但是每次累加都是獨立的小索引。
Elasticsearch底層依賴的Lucene,引入了 per-segment search 的概念。一個段(segment)是有
完整功能的倒排索引,但是現在Lucene中的索引指的是段的集合,再加上提交點。
索引vs分片
爲了避免混淆,需要說明,Lucene索引是Elasticsearch中的分片,Elasticsearch中的索引是分片的集合。當Elasticsearch搜索索引時,它發送查詢請求給該索引下的所有分
片,然後過濾這些結果,聚合成全局的結果。
更新過程
1. 新的文檔首先寫入內存區的索引緩存。
2. 不時,這些buffer被提交:
2.1)一個新的段——額外的倒排索引——寫入磁盤。
2.2)新的提交點寫入磁盤,包括新段的名稱。
2.3)磁盤是fsync’ed(文件同步)——所有寫操作等待文件系統緩存同步到磁盤,確保它們
可以被物理寫入。
3. 新段被打開,它包含的文檔可以被檢索
4. 內存的緩存被清除,等待接受新的文檔。
3.緩存進磁盤
在緩存區數據,不可能實時往磁盤寫入同步,這樣太耗費磁盤性能了。但是同步太慢的話,又會有寫入的數據無法快速查到的問題。ES提供了每秒自動同步一次的服務,並且提供了refeash API用於手動同步。
POST /_refresh <1>
POST /blogs/_refresh <2>
PUT /my_logs//設置自動同步時間
{
"settings": {
"refresh_interval": "30s" <1>
}
}
4.持久化
這一點和mysql的redolog,防止內存中的提交因爲關機而丟失,專門針對這部分未提交的內存中的數據做持久化。在ES中稱爲事務日誌translog
1. 當一個文檔被索引,它被加入到內存緩存,同時加到事務日誌。
2. refresh使得分片的進入如下圖描述的狀態。每秒分片都進行refeash:
內存緩衝區的文檔寫入到段中,但沒有fsync。
段被打開,使得新的文檔可以搜索。
緩存被清除
3. 隨着更多的文檔加入到緩存區,寫入日誌,這個過程會繼續
4. 不時地,比如日誌很大了,新的日誌會創建,會進行一次全提交:
內存緩存區的所有文檔會寫入到新段中。
清除緩存
一個提交點寫入硬盤
文件系統緩存通過fsync操作flush到硬盤
事務日誌被清除
事務日誌記錄了沒有flush到硬盤的所有操作。當故障重啓後,ES會用最近一次提交點從硬盤恢復所有已知的段,並且從日誌裏恢復所有的操作。事務日誌還用來提供實時的CRUD操作。當你嘗試用ID進行CRUD時,它在檢索相關段內的文檔前會首先檢查日誌最新的改動。這意味着ES可以實時地獲取文檔的最新版本。
5.合併段
此處類似redis aof的重寫達到的效果。
ES通過後臺合併段解決這個問題。小段被合併成大段,再合併成更大的段。這是舊的文檔從文件系統刪除的時候。舊的段不會再複製到更大的新段中。修改和刪除在這裏免除了重複,得到了真正的實現。
1. 索引過程中,refresh會創建新的段,並打開它。
2. 合併過程會在後臺選擇一些小的段合併成大的段,這個過程不會中斷索引和搜索。
3. 下圖描述了合併後的操作:
新的段flush到了硬盤。
新的提交點寫入新的段,排除舊的段。
新的段打開供搜索。
舊的段被刪除。