在使用 Elasticsearch 時,頻繁更新文檔是一種常見誤區。這不僅影響性能,還可能導致系統資源的浪費。
理解 Elasticsearch 的文檔更新機制對于優化性能至關重要。
關于 Elasticsearch 更新操作,常見問題如下:
——https://t.zsxq.com/bDxwL
1、頻繁更新的挑戰
在關系型數據庫中,更新操作在事務完成后立即生效,查詢結果可以立刻反映變化。
而在 Elasticsearch 中,更新操作則依賴于刷新(refresh,如下圖標紅部分)過程。這增加了額外的開銷,特別是在頻繁更新的場景下。
細節參見《一本書講透Elasticsearch》第342-343頁詳細闡釋。
2、文檔更新的步驟
Elasticsearch 更新的本質可以分為以下幾個步驟:
2.1 查找文檔
首先,Elasticsearch 根據請求中的文檔 ID 或查詢條件,在索引中查找需要更新的文檔。
2.2 讀取并更新
找到文檔后,Elasticsearch 會將文檔加載到內存中,并根據請求中的更新內容修改文檔數據。這包括字段的增加、修改或刪除。
2.3 版本控制
Elasticsearch 使用版本號或樂觀鎖定機制,確保并發更新時數據的一致性。每次更新,版本號都會增加,以避免更新沖突。
示例:首次寫入文檔,version是 1。
查看索引分段信息如下:
2.4 重新索引
修改后的文檔并不會直接更新到原位置,而是作為一個新文檔寫入索引。這是因為 Elasticsearch 使用不可變的段文件來存儲數據。
繼續剛才的示例:更新操作執行一次后,截圖如下:_version
由 ?1 變成 2。
更新后查看分段:
文檔數顯示為1(如下圖),但其實是兩個不同的分段(如上圖)。
2.5 舊文檔標記刪除
原始文檔被標記為刪除。刪除標記會在段合并時清理,以節省存儲空間。
在如下示例中,通過 _delete_by_query 可以看到標記刪除的過程。標記的文檔將在段合并時被清理。
2.6 刷新與合并
更新完成后,Elasticsearch 定期刷新內存中的變更到磁盤,并合并段文件以優化存儲和查詢性能。
這些步驟確保了 Elasticsearch 在處理更新時的高效性和數據一致性。
更多細節操作參見源碼:
https://github.com/elastic/elasticsearch/blob/main/server/src/main/java/org/elasticsearch/action/update/UpdateHelper.java
3、更新操作的代價
每次更新都涉及到重新索引,而不是簡單的“原地”修改。這會增加磁盤 I/O 和計算資源的使用。
此外,標記為刪除的文檔在段合并前仍然占用空間,增加了存儲負擔。
第二部分的截圖能讓我們進一步理解:為什么越更新文檔存儲占據磁盤空間越大,為什么越刪除文檔存儲占據磁盤越大的原因。
同時,進一步理解,段合并之后,磁盤空間驟降!
4、性能優化建議
4.1. 減少更新頻率
實戰場景:對于用戶行為數據(如瀏覽次數、點贊數),可以合并多次更新為一次批量更新。
建議1:設置一個合理的批量更新間隔,比如每隔 5 分鐘更新一次,而不是每次用戶操作后立即更新。
建議2:使用消息隊列收集用戶操作,定時批量更新。
4.2. 批量處理
實戰場景:在電商平臺中,商品信息的批量更新。
建議:使用 _bulk API 一次性更新多個文檔,減少單次請求的開銷。
實踐參考:
POST?_bulk
{?"update":?{"_id":?"1"}?}
{?"doc":?{"price":?100}?}
{?"update":?{"_id":?"2"}?}
{?"doc":?{"price":?200}?}
4.3. 延遲刷新
實戰場景:日志數據的批量插入場景。
建議:對不需要實時可見性的索引,增加 refresh_interval,比如設置為 30s 或 60s。
實現:
PUT?/my_index/_settings
{"refresh_interval":?"30s"
}
4.4. 合理的索引設計
實戰場景:對于大規模數據的索引設計,避免不必要的字段更新。
建議1:僅索引必要的字段,避免在頻繁更新時更新整個文檔。
PUT?/my_index
{"mappings":?{"properties":?{"title":?{"type":?"text"},"views":?{"type":?"integer",?"index":?false}}}
}
建議2:在設計階段多花時間,考慮建模的充分性,在創建索引時明確指定需要索引的字段。
建議3:能 ingest pipeline 預處理管道或者 logstash filter 中間過濾階段搞定的,咱們就不要拖到實現階段。
如下問題的解決方案就是借助:json processor 實現。相比于更新操作,寫入前的預處理非常有必要!
5、結論
頻繁更新文檔是 Elasticsearch 使用中的一個常見誤區。
理解其更新機制和潛在開銷是進行系統優化的關鍵。通過減少更新頻率、使用批量處理、延遲刷新等策略,可以顯著提高系統的性能和資源利用率。Elasticsearch 的強大功能需要合理使用,才能充分發揮其優勢。
希望這篇文章能夠幫助你更好地理解和優化 Elasticsearch 的使用!
參考:
https://betterprogramming.pub/boosting-elasticsearch-cluster-performance-3-proven-tips-9b718a9114bc
https://www.youtube.com/watch?v=gWXkAhnYFYw
Elasticsearch 使用誤區之一——將 Elasticsearch 視為關系數據庫!
Elasticsearch 為什么會產生文檔版本沖突?如何避免?
更短時間更快習得更多干貨!
和全球超2000+?Elastic 愛好者一起精進!
elastic6.cn——ElasticStack進階助手
比同事搶先一步學習進階干貨!