ElasticSearch 系列文章
1 ES 入門之一 安裝ElasticSearcha
2 ES 記錄之如何創建一個索引映射
3 ElasticSearch 學習記錄之Text keyword 兩種基本類型區別
4 ES 入門記錄之 match和term查詢的區別
5 ElasticSearch 學習記錄之ES幾種常見的聚合操作
6 ElasticSearch 學習記錄之父子結構的查詢
7 ElasticSearch 學習記錄之ES查詢添加排序字段和使用missing或existing字段查詢
8 ElasticSearch 學習記錄之ES高亮搜索
9 ElasticSearch 學習記錄之ES短語匹配基本用法
10 ElasticSearch 學習記錄之 分布式文檔存儲往ES中存數據和取數據的原理
11 ElasticSearch 學習記錄之集群分片內部原理
12 ElasticSearch 學習記錄之ES如何操作Lucene段
13 ElasticSearch 學習記錄之如任何設計可擴容的索引結構
14 ElasticSearch之 控制相關度原理講解
分片內部原理
-
分片是如何工作的
- 為什么ES搜索是近實時性的
- 為什么CRUD 操作也是實時性
- ES 是怎么保證更新被持久化時斷電也不丟失數據
- 為什么刪除文檔不會立即釋放空間
- refresh, flush, 和 optimize API 作用
-
使文本可被搜索
倒排索引的結構詞項 文檔列表
Term | Doc 1 | Doc 2 | Doc 3 | ...brown | X | | X | ...
fox | X | X | X | ...
quick | X | X | | ...
the | X | | X | ... -
倒排索引的不變性
- 不需要鎖
- 可被內核的文件系統緩存,停留在內存中,大部分請求會直接請求到內存,不會落到磁盤上
- filter緩存,在索引的生命周期始終有效。不需要再每次數據改變時重建
- 寫入單個較大的倒排索引使允許數據被壓縮
-
如何在索引不變情況下 動態更新索引
-
使用更多的索引,來解決這個問題
-
通過增加新的補充索引來反映新近的修改,而不是直接重寫整個倒排索引
-
一個 Lucene 索引包含一個提交點和三個段

-
逐段搜索的流程
- 新文檔被收集到內存索引緩存
- 不時地, 緩存被 提交
- 一個新的段----一個追加的倒排索引--被寫入磁盤
- 一個新的包含新段名字的 提交點 被寫入磁盤
- 磁盤進行 同步 — 所有在文件系統緩存中等待的寫入都刷新到磁盤
- 新的段被開啟,讓它包含的文檔可見以被搜索
- 內存緩存被清空,等待接收新的文檔
-
一個在內存緩存中包含新文檔的 Lucene 索引
-

-
在一次提交后,一個新的段被添加到提交點而且緩存被清空
-

-
-
刪除和更新文檔
- 段是不可改變的,每個提交點都會有一個.del文件。在這個文件中能列出這些刪除文檔的短信息
- 當文檔被刪除時不是刪除,只是在.del文件中被登記
- 文檔的更新也是這樣的,先將更新的文檔標記為刪除。然后文檔的新版本被索引到一個新的段中
近實時搜索
-
提交(Commiting)一個新的段到磁盤需要一個 fsync 來確保段被物理性地寫入磁盤,這樣在斷電的時候就不會丟失數據。但是每次提交的一個新的段都fsync 這樣操作代價過大。可以使用下面這種更輕量的方式
-
在內存緩沖區中包含了新文檔的 Lucene 索引
-

-
Lucene 允許新段被寫入和打開--使其包含的文檔在未進行一次完整提交時便對搜索可見
-
-
緩沖區的內容已經被寫入一個可被搜索的段中,但還沒有進行提交
-

-
這里新段會被先寫入到文件系統緩存--這一步代價會比較低,稍后再被刷新到磁盤--這一步代價比較高
-
-
默認情況下每個分片會每秒自動刷新一次
- 近 實時搜索: 文檔的變化並不是立即對搜索可見,但會在一秒之內變為可見
- POST /_refresh // 刷新Refresh 所有的索引
- POST /blogs/_refresh // 只刷新Refresh blogs 索引
可以在settings 設置對定時刷新頻率的大小
PUT /my_logs
{
"settings": {
"refresh_interval": "30s" //30秒刷新一次
"refresh_interval": "-1" //關閉自動刷新
"refresh_interval": "1s"//每秒自動刷新
}
}
持久化變更
在沒有 fsync 把數據從內存刷新到硬盤中,我們不能保證數據在斷電或程序退出時之后依然存在
- 即時每秒刷新,也不能實現近實時搜索。我們任然有另外的方法確保從失敗中回復數據
- ES 增加一個translog,或者叫做事務日志。在每次操作是均進行日志記錄
- 整個流程是如下的操作
-
一個文檔被索引之后,就會被添加到內存緩沖區,並且 追加到了 translog
-
-
刷新(refresh)使分片處於緩存被清空,但是事務日志不會的狀態
- 內存緩沖區的文檔被寫入新的段中,但是沒有進行fsync
- 段被打開,且可被搜索到
- 內存緩沖區被清空

-
進程繼續進行,更多的文檔被添加到內存緩沖區和追加的事務日志中
-
每隔一段時間,translog太大 或 索引被刷新。一個新的translog被創建,並且被全量提交
-
- 所有內存緩沖區的文檔都被寫入一個新的段中
- 緩沖區內清空
- 一個提交點被寫入硬盤
- 文件系統緩存通過fsync被刷新
- 老的translog 被刪除
-
- translog 提供所有沒有被刷新到磁盤操作的一個持久化記錄。當ES啟動時,會根據最后一個提交點去恢復已知的段
- translog 也可供用來提供實時的CRUD。但我們進行一些CRUD操作時,它會首先檢查translog任何最近的變更。
- flush API ** 執行一次提交,並截斷translog**的操作
-
分片默認每30M自動flush一次。translog太大也會自動flush
-
可通過自己執行flush API操作
POST /blogs/_flush //刷新索引
POST /_flush?wait_for_ongoing //刷新索引並等待所有的刷新結果返回
-
段合並
-
段合並的時候會將那些舊的已刪除的文檔從文件系統中刪除,被刪除或者被更新的文檔不會被復制到新的大段中
-
段合並的流程
-
- 當索引的時候,刷新(refresh)操作會創建新的段
- 合並的時候會選擇一部分大小相似的段,並且將其合並到更大的段中
- 段的合並結束,老的段就要被刪除

-
optimized API 的作用
- optimize API大可看做是 強制合並 API 。

