Elasticsearch 併發衝突處理機制

2021-10-10 19:45:26 字數 2120 閱讀 7528

在電商場景下,工作流程為:

讀取商品資訊,包括庫存數量

使用者下單購買

更新商品資訊,將庫存數減一

如果是多執行緒操作,就可能有多個執行緒併發的去執行上述的3步驟流程,假如此時有兩個人都來讀取商

品資料,兩個執行緒併發的服務於兩個人,同時在進行商品庫存資料的修改。假設庫存為100件 正確的情

況:執行緒a將庫存-1,設定為99件,執行緒b接著讀取99件,再-1,變為98件。如果a,b執行緒都讀取的為

100件,a處理完之後修改為99件,b處理完之後再次修改為99件,此時結果就出錯了

put

/test_index/_doc/

4

模擬兩個客戶端,都獲取到了同一條資料

get

/test_index/_doc/

4# 返回

}

put

/test_index/_doc/

4

返回

,"_seq_no":1

,"_primary_term":1

}

put

/test_index/_doc/

4?if_seq_no=

0&if_primary_term=

1

會出錯

],「type」: 「version_conflict_engine_exception」,

「reason」: 「[4]: version conflict, required seqno [0], primary term [1]. current document has seqno [1] and primary term [1]」,

「index_uuid」: 「qm83o5m4tzi5qci8v1lcyq」,

「shard」: 「0」,

「index」: 「test_index」

},「status」: 409

}

樂觀鎖就成功阻止併發問題

在樂觀鎖成功阻止併發問題之後,嘗試正確的完成更新

重新進行get請求,得到 version

基於最新的資料和版本號(以前是version 現在是if_seq_no和if_primary_term ),去進行修改,修

改後,帶上最新的版本號,可能這個步驟會需要反覆執行好幾次,才能成功,特別是在多執行緒併發

更新同一條資料很頻繁的情況下

put

/test_index/_doc/

4?if_seq_no=

1&if_primary_term=

1

es提供了乙個feature,就是說,你可以不用它提供的內部_version版本號來進行併發控制,可以基於你

自己維護的乙個版本號來進行併發控制。

?version=1&version_type=external
區別在於,version方式,只有當你提供的version與es中的version一模一樣的時候,才可以進行修改,只要不一樣,就報錯;當version_type=external的時候,只有當你提供的version比es中的_version大的時候,才能完成修改

es,if_seq_no=0&if_primary_term=1和 文件中的值相等 才能更新成功

es,_version=1,?version>1&version_type=external,才能成功,比如說?

version=2&version_type=external

put

/test_index/_doc/

5

put

/test_index/_doc/

5?version=

2&version_type=external

p

ut/test_index/_doc/

5?version=

3&version_type=external

ElasticSearch 併發操作問題

解決併發問題 問題的原因是 elasticsearch 不支援 acid 事務。對單個檔案的變更是 acidic 的,但包含多個文件的變更不支援。如果你的主要資料儲存是關聯式資料庫,並且 elasticsearch 僅僅作為乙個搜尋引擎 或一種提公升效能的方法,可以首先在資料庫中執行變更動作,然後在...

Elasticsearch 併發修改樂觀鎖

來自 1 elasticsearch 的樂觀鎖,可以使用外部系統提供的版本號 這時elasticsearch將只檢查提供的版本是否比當前儲存在索引中的版本大 大多少不重要 如果是成功,否則失敗。在elasticsearch中,更新請求實際上是分為兩個階段,獲取文件,修改文件,然後儲存文件。那麼當兩個...

elasticsearch配置詳解

elasticsearch的config資料夾裡面有兩個配置檔案 elasticsearch.yml和logging.yml,第乙個是es的基本配置檔案,第二個是日誌配置檔案,es也是使用log4j來記錄日誌的,所以logging.yml裡的設定按普通log4j配置檔案來設定就行了。下面主要講解下e...