版本控制:數據庫
在關係數據庫管理系統裏,悲觀併發控制(又名「悲觀鎖」,Pessimistic Concurrency Control,縮寫「PCC」)是一種併發控制的方法。當咱們在讀取一個數據前先鎖定這一行,而後確保只有讀取到數據的這個線程能夠修改這一行數據。架構
ES使用的是樂觀併發控制(又名」樂觀鎖」,Optimistic Concurrency Control,縮寫」OCC)。 ES不會阻止某一數據的訪問,然而,若是基礎數據在咱們讀取和寫入的間隔中發生了變化,更新就會失敗,這時候就由程序來決定如何處理這個衝突。它能夠從新讀取新數據來進行更新,又或者將這一狀況直接反饋給用戶。併發
ES中的樂觀鎖curl
當咱們發送get請求的時候 post /exindex/exindex/AVyAgBvA9tISzc84d_4i/返回值爲:post
{ "_index": "exindex", "_type": "exindex", "_id": "AVyAgBvA9tISzc84d_4i", "_version": 1, "found": true, "_source": { "school": "支付寶在扣款事務提交以前,向實時消息服務請求發送消息", "name": "sony", "age": "14" } }
這裏_version是1,咱們從ES中查詢到一條記錄,修改完成之後從新PUT創建索引,這時候咱們要把_version做爲一個參數傳遞過去,ES會用該參數和實際的數據進行比對,若是相同則進行重建索引,若是不一樣則返回錯誤信息。請求url 帶上本次版本號,而且指定docId,請求以下:
curl -XPUT http://121.49.129.155:9200/exindex/exindex/AVyAgBvA9tISzc84d_4i?version=1 -d' { "name": "Jane", "age": 80, "school": "清華大學" }'
文檔修改結束後,返回成功後再次查詢後獲得的版本號已經變動完畢,_version已經變動爲2url
{ "_index": "exindex", "_type": "exindex", "_id": "AVyAgBvA9tISzc84d_4i", "_version": 2, "found": true, "_source": { "name": "Jane", "age": 80, "school": "清華大學" } }
當咱們再次傳遞版本號爲_version=1去嘗試更新文檔的時候,會報出版本衝突錯誤 "error":{"root_cause":[{"type":"version_conflict_engine_exception","reason":"[exindex][AVyAgBvA9tISzc84d_4i]: version conflict, current [2] ,當咱們將版本號變動_version=2做爲參數傳遞後,再次修改文檔更新成功,版本號自動增長。線程
{ "_index": "exindex", "_type": "exindex", "_id": "AVyAgBvA9tISzc84d_4i", "_version": 3, "found": true, "_source": { "name": "Jane", "age": 80, "school": "北京大學" } }
使用外部版本號控制系統版本控制
一種比較常見的架構應用就是使用一些其餘的數據庫做爲主應用數據庫,es只是做爲一個檢索引擎使用,這也就不可避免的考慮到數據的一致性,數據的版本問題也就出現了。code
若是你的數據庫已經存在了版本號,或者是能夠表明版本timestamp的時間戳。這時就能夠在es的查詢url後面添加version_type=external來使用這些號碼。 注意:版本號碼必需要是大於0小於9223372036854775807(Java中long的最大正值)的整數。索引
外部版本號與以前說的內部版本號在處理的時候有些不一樣。它再也不檢查_version是否與請求中指定的一致,而是檢查是否小於指定的版本。若是請求成功,外部版本號就會被存儲到_version中。
例如,建立一個包含外部版本號爲5的新的文檔,咱們能夠這樣作: curl -XPOST '/testindex/fulltext/1?version=5&version_type=external' -d'{"title":"external log","content":"hello es"}'
查詢返回的結果爲:
{ "_index": "testindex", "_type": "fulltext", "_id": "1", "_version": 5, "found": true, "_source": { "title": "external log", "content": "hello es" } }
如今咱們更新文檔將文檔的版本號指定爲8:
{ "_index": "testindex", "_type": "fulltext", "_id": "1", "_version": 8, "found": true, "_source": { "title": "external log second operate", "content": "hello es" } }
版本號已經變動爲"_version": 8,從新執行請求,返回的異常一樣爲版本衝突錯誤。
總結:在實際開發中根據不一樣的業務場景使用不一樣的版本控制,這個仍是須要業務場景具體選擇。