在生產環境下,無論使用Elasticsearch做檢索還是ELK分析的,如果文檔數量非常龐大,動輒就是按T計算。Elasticsearch也提供了文檔的批處理機制,允許一次性檢索多個文檔。為了保證集群處在一個最佳負載狀態,我們會通過Delete By Query的方式去定期刪除索引中的數據。
Delete By Query API 介紹
根據特定的查詢條件對ES相關索引中某些特定的文檔進行批量刪除。
POST index_name/_delete_by_query
{
"query": { //這些是自定義查詢條件,根據查詢條件去批量刪除
"match": {//請求體跟Search API是一樣的
"message": "some message"
}
}
}
Delete By Query 刪除原理
在Elasticsearch中刪除和更新都是寫操作,但Elasticsearch中的文檔是不可變的,因此不能通過更新或者刪除以展示其變化。
Delete_by_query並不是真正意義上物理文檔刪除,而是只是版本變化並且對文檔增加了刪除標記。當我們再次搜索的時候,會搜索全部然后過濾掉有刪除標記的文檔。因此,該索引所占的空間並不會隨着該API的操作磁盤空間會馬上釋放掉,只有等到下一次段合並的時候才真正被物理刪除,這個時候磁盤空間才會釋放。相反,在被查詢到的文檔標記刪除過程同樣需要占用磁盤空間,這個時候,你會發現觸發該API操作的時候磁盤不但沒有被釋放,反而磁盤使用率上升了。
使用Delete By Query 刪除API注意事項
1.一般生產環境中,使用該API操作的索引都很大,文檔都是千萬甚至數億級別。索引大小在幾百G甚至幾個T,因此,這個操作建議在業務低峰期或者晚上進行操作,因為大數據量情況下刪除的需要消耗較多的i/o CPU 資源,容易對生產集群造成影響。
2.在刪除過程中要確定集群磁盤有一定的余量,因為標記刪除需要占用磁盤空間。如果磁盤空間不夠,這個操作的失敗率還是很大的。
段合並 --> 強制合並
由於自動刷新流程每秒會創建一個新的段,這樣會導致段時間內的段數量暴增。而段數目太多會帶來較大的麻煩。每個段都會消耗文件句柄、內存和CPU運行周期。更重要的是,每個請求都必須輪流檢查每個段;所以段越多,搜索也就越慢。Elasticsearch通過在后台進行段合並來解決這個問題。小的段被合並到大的段,然后這些大的段再被合並到更大的段。段合並的時候會講那些舊的一刪除的文檔從文件系統中清除。被刪除的文檔(或被更新文檔的舊版本)不會被拷貝到新的大段中。啟動段合並並不需要你做任何事。進行索引和搜索時會自動進行。
Elasticsearch會有后台線程根據lucene的合並規則定期進行段合並操作,一般不需要用戶擔心或者采取任何行動。被刪除的文檔在合並時,才會被真正刪除掉。再次之前,它仍然會占用着JVM heap和操作系統的文件cache、磁盤等資源。在某些特定情況下,我們需要ES強制進行段合並,以釋放其占用的大量系統、磁盤等資源。POST /index_name/_forcemerge
。
_forcemerge 命令可強制進行segment合並,並刪除所有標記為刪除的文檔。Segment merging要消耗CPU,以及大量的I/O資源,所以一定要在你的ElasticSearch集群處於維護窗口期間,並且有足夠的I/O空間的(如:SSD)的條件下進行;否則很可能造成集群崩潰和數據丟失。
_forcemergeAPI 有幾個常用的參數:
- max_num_segments: 是表示將某個索引的每個分片強制合並為幾個段的意思。
- only_expunge_deletes: 是表示僅將標記刪除為文檔的進行強制合並物理刪除,不進行其它合並操作。
參考
https://www.elastic.co/guide/en/elasticsearch/reference/7.2/docs-delete-by-query.html
https://www.elastic.co/guide/en/elasticsearch/reference/7.2/indices-forcemerge.html#indices-forcemerge
https://www.jianshu.com/p/60a6ad164035