elasticsearch中版本號(version)的問題

    今天在分析ES的索引的創建過程中看到了些和version相關的變量(例如:versionForIndexing)。這些個變量是幹什麼的呢?

    答:用於衝突處理的。

    在ES的應用場景中,使用index API更新文檔,可以一次性讀取原始文檔,做修改,然後重新索引整個文檔,最近的索引請求將獲勝:無論最後哪一個文檔被索引,都將唯一存儲在ElasticSearch中,如果其他人同時更改了這個文檔,他們的更改將丟失。

    很多時候丟失信息是沒問題的。也許我們的主數據存儲是一個關係型數據庫,我們只是將數據複製到ElasticSearch中並使其可被搜索;也許兩個人同時更改文檔的機率很小 。或者對於某些業務來說偶爾丟失更改並不是很嚴重的問題。

    但,有時候丟失一個變更就是非常嚴重的。試想我們使用ElasticSearch存儲我們網上商城商品庫存的數量,每次我們賣一個商品的時候,在ElasticSearch中將庫存數量減少(促銷時一個時間點賣很多商品)。或是金融系統兩個人同時對一個賬戶進行取錢操作。都存在如下圖中存在的問題:


在數據庫領域中,有兩種方法通常備用來確保併發更新時變更不會丟失:

    1、悲觀併發控制

        這種方法被關係型數據庫廣泛使用,它假定有變更衝突可能發生,因此阻塞訪問資源以防止衝突。一個典型的例子是讀取一行數據之前先將其鎖住,確保只有放置鎖的線程能夠對這行數據進行修改。

    2、樂觀併發控制

        Elasticsearch 中使用的這種方法,它假定衝突是不可能發生的,所以不會阻塞正在嘗試的操作。 然而,如果源數據在讀寫當中被修改,更新將會失敗。應用程序接下來將決定該如何解決衝突。 例如,可以獲取新的數據,重試更新、或者將相關情況報告給用戶。

===============================================

    ElasticSearch是分佈式的,當文檔創建、更新、刪除時,新版本的文檔必須複製到集羣中其他節點,同時,ElasticSearch也是異步和併發的。這就意味着這些複製請求被並行發送,並且到達目的地時也許順序是亂的(老版本可能在新版本之後到達)。ElasticSaerch需要一種方法確保文檔的舊版本不會覆蓋新的版本:ES利用_version (版本號)的方式來確保應用中相互衝突的變更不會導致數據丟失。需要修改數據時,需要指定想要修改文檔的version號,如果該版本不是當前版本號,請求將會失敗。

詳細例子參見:連接

ElasticSearch中有內部版本號外部版本號之分。使用內部版本號是要求指定的version字段和當前的version號相同。但在使用外部版本號時要求當前version號小於指定的版本號。如果請求成功,外部版本號作爲文檔新的version號進行存儲。詳細參見:連接

外部版本號命令:
PUT /website/blog/2?version=5&version_type=external
內部版本號命令:
PUT /website/blog/1?version=1 

參考文章:

https://elasticsearch.cn/book/elasticsearch_definitive_guide_2.x/optimistic-concurrency-control.html

https://elasticsearch.cn/book/elasticsearch_definitive_guide_2.x/version-control.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章