圖解 Elasticsearch 寫入流程
整體上看,Client 向 ES 發送寫請求,es 接收數據,寫入磁盤文件,返回響應給 Client 寫入成功,這樣就完成了。
然後拉近看一下,看看內部都做了什麼工作。
- ES 整體結構
ES 集羣裏面有多個 Server 節點,一個 ES Index 有多個 shard 分片,每個 shard 有多個副本。
其中有一個 primary 主副本,負責寫入,其他副本爲 replica,不能寫,只能同步 primary 的數據,但可以處理讀請求。
ES 收到寫請求後,會將請求路由到目標 shard 的 primary 副本。
每一個 shard 就是一個 Lucene Index,包含多個 segment 文件,和一個 commit point 文件。
segment 文件存儲的就是一個個的 Document,commit point 記錄着都有哪些 segment 文件。
瞭解了 ES 的整體結構,可知 primary shard 收到寫請求,就是把 Document 數據寫入 segment。
- 直接寫 Segment 效率低怎麼辦?
如果每次寫操作都是直接落盤的話,I/O 效率會比較低。
所以,ES 使用了一個內存緩衝區 Buffer,先把要寫入的數據放進 buffer。
內存性能好,但不安全,會丟數據,所以 es 使用了一個日誌文件 Translog。就像 MySQL 的 Binlog,記錄着每一條操作日誌,如果 ES 出現故障,重啓之後可以從 Translog 中恢復數據。
因爲日誌文件只是單純的做內容追加,沒有其他邏輯操作,所以寫入速度很快。
並不是每條操作直接寫入磁盤,也是有一個內存緩衝,每隔 5 秒寫入磁盤。所以,極端情況下會有 5 秒數據的丟失,如果要嚴格保證數據安全,可以調整這個時間。
這樣,數據來到 primary shard 之後,先是進入 buffer,並把操作記錄寫入 Translog。
- Buffer 中數據怎麼寫入 Segment 文件?
ES 每隔一秒執行一次 refresh 操作,會創建一個 Segment 文件,將 buffer 中的數據寫入這個 segment,並清空 buffer。
進入 segment 的數據就進入了 Lucene,建立好了倒排索引,可以被搜索到。
- 如何進一步提升寫 Segment 效率?
需要注意,ES 雖然把數據寫入了 segment 文件,但實際上還沒有真正落盤,因爲操作系統的文件系統也是有緩存的,這是操作系統層面的性能優化,由操作系統決定物理落盤時間,除非程序寫文件時使用同步寫 fsync。
ES 爲了性能自然沒有使用 fsync,因爲有 Translog 記錄了所有操作步驟。
雖然可能還沒實際寫入 segment 物理文件,但只要進入了操作系統的文件系統,就可以被搜索了,這一點不用擔心。
- Translog 日誌文件越來越大怎麼辦?
隨着寫入數據的增加,Translog 也越來越大,需要清理。
觸發清理動作需要 2 個條件:
-
大小觸發設定的閾值
-
30 分鐘
任意條件滿足即觸發一次 commit 提交操作。
操作流程:
-
執行 refresh 操作。
-
把這次提交動作之前所有沒有落盤的 segment 強制刷盤,確保寫入物理文件。
-
創建一個提交點,記錄這次提交對應的所有 segment,寫入 commit point 文件。
-
清空 Translog,因爲 Segment 都已經踏實落地了,之前的 Translog 就不需要了。
這個提交流程,稱爲 flush。
- Segment 太多怎麼辦?
通過上面的流程,可以發現,segment 文件太多了,一秒就產生一個,這會嚴重影響搜索性能。
es 有一個後臺程序,用於 merge 合併這些 segment 文件,把小 segment 整合到一個大的 segment 中,並修改 commit point 的 segment 記錄。
merge 過程還會清理被刪除的數據。
es 接收到刪數據請求時,不會真的到 segment 中把數據刪了,而是把要刪除的數據寫到 '.del' 文件中,在讀操作時,會根據這個文件進行過濾。
merge 合併時才真正刪除,合併後的 segment 中就沒有已經刪除的數據了。
- 小結
寫操作時,ES 把寫請求路由到目標 Shard 所在的 Server 節點,Doc 先被放入 Buffer,並記錄此請求的操作日誌,寫入 Translog。
每隔一秒,執行 Refresh 操作,將 Buffer 中數據寫入 Segment 文件,並清空 Buffer。
Refresh 實際寫入的 Segment 文件緩存,會在 Flush 操作中刷盤到物理文件。
當 Translog 過大,或者每隔 30 分鐘,執行一次 Flush 操作。
先執行一次 Refresh,然後將所有 Segment 文件緩存刷盤到物理文件,並創建提交點,記錄此次操作設計的 Segment,寫入 Commit Point 文件,最後清空 Translog。
ES 的 Merge 程序負責合併小 Segment,並清除被刪除的 Document。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/ZgOsGXo4ApQiOXoRJv_jfw