Elasticsearch文檔版本沖突原理與解決


一般我們在更新文檔時,主要的操作流程時:讀取文檔->修改->提交保存。數據中心等保存的都是最新一次提交的內容。

大部分時候,這都沒有什么問題。但是如果兩個或更多的請求同時修改一個文檔時,非常容易產生沖突,因為上述的流程無法保證原子性,也不可能保證。
沖突解決常用的兩種策略:

    1. 悲觀鎖並發策略
      在關系性數據庫中,通過阻塞並排隊的方式,來避免發生沖突,例如在讀取數據行時阻塞,來保證正在修改行數據的請求完成正常操作后,以讀取到最新的數據。這種方式的前提假設是數據沖突更有可能發生。
    2. 樂觀鎖並發策略
      Elasticsearch中采用的是樂觀鎖的並發策略,這種方式的前期假設是數據沖突一般不會發生,從而避免阻塞數據請求。然而,在讀和寫之間,如果數據發生改變,更新就失敗了,然后由程序決定如果進行后續的處理。

  Elasticsearch是分布式的,文檔的創建/變更等都會同步到其他節點。由於其異步性和並發的特點,這些同步請求都是並行的,因此並不能保證數據的是按照修改順序依次到達的。Elasticsearch保證了一個老版本的數據永遠無法重寫或覆蓋更新版本的數據。在 index get 和 delete請求中,都存在一個 _version 字段。數據的變更均會導致_version的值增大。Elasticsearch通過該字段來保證小於該值的數據會被忽略掉。通過數字版本的方式也可以避免ABA的數據問題,即數據A修改為B而后又修改為A,對於應用端來說,數據是沒有任何變化的。

創建文檔: 

1 PUT /website/blog/1/_create
2 {
3   "title": "My first blog entry",
4   "text":  "Just trying this out..."
5 }

獲取文檔:

 1 GET /website/blog/1
 2 結果:
 3 {
 4   "_index" :   "website",
 5   "_type" :    "blog",
 6   "_id" :      "1",
 7   "_version" : 1,
 8   "found" :    true,
 9   "_source" :  {
10       "title": "My first blog entry",
11       "text":  "Just trying this out..."
12   }
13 }

此時 _version 為1

修改數據:

1 PUT /website/blog/1?version=1 
2 {
3   "title": "My first blog entry",
4   "text":  "Starting to get the hang of this..."
5 }
1 {
2   "_index":   "website",
3   "_type":    "blog",
4   "_id":      "1",
5   "_version": 2
6   "created":  false
7 }

此時操作成功。

如果在_version為1的基礎我們再次提交修改:

 1 {
 2    "error": {
 3       "root_cause": [
 4          {
 5             "type": "version_conflict_engine_exception",
 6             "reason": "[blog][1]: version conflict, current [2], provided [1]",
 7             "index": "website",
 8             "shard": "3"
 9          }
10       ],
11       "type": "version_conflict_engine_exception",
12       "reason": "[blog][1]: version conflict, current [2], provided [1]",
13       "index": "website",
14       "shard": "3"
15    },
16    "status": 409
17 }

此時,顯示存在版本沖突。此時應用可以據此作出相應的處理,獲取最新數據Merge處理亦或其他處理方式。

 

問題解決:在請求上加上retry_on_conflict的參數,在沖突發生時,重試提交數據:

1 POST /website/pageviews/1/_update?retry_on_conflict=5 
2 {
3    //some update
4 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM