GET test1/_doc/1
可以擷取如下資訊:
"_index" : "test1",
"_type" : "_doc",
"_id" : "1",
"_version" : 5,
"_seq_no" : 20797327,
"_primary_term" : 2,
"found" : true,
...
_version:文檔版本,每次更新文檔時遞增。
_seq_no:配置給文檔的序列号用來進行索引操作,用于確定文檔的舊版本不會覆寫新版本。
_primary_term:配置給文檔的主term用來進行索引操作。
索引文檔可以通過
if_seq_no
和
if_primary_term
參數進行目前文檔版本的判斷,如指定參數和目前文檔版本一緻則滿足索引條件修改文檔并且seq_no增加一,則會抛出
VersionConflictException
409
。
通過使用
_create
或者将
op_type
設定為create(預設為index)可實作僅索引不存在的文檔(通過id辨識)。
版本控制:
每個文檔都有一個版本号。預設的内置版本号從1開始每次更新或删除的時候遞增(
_primary_term
預設1,
_version
_seq_no
随更新删除同步遞增)。也可以将版本号設定為外部值(資料庫中維護),設定
version_type
為
external
開啟,數值型,值必須大于等于0小于9.2e+18。
使用外部類型時,系統會檢查傳遞給索引請求的版本号是否大于目前存儲文檔的版本。如果為 true,則文檔将被索引并使用新版本号;如果提供的值小于或等于存儲文檔的版本号,則會發生版本沖突,索引操作将失敗(409)。例如:
PUT my-index-000001/_doc/1?version=2&version_type=external
{
"user": {
"id": "elkbee"
}
}
版本類型version_type:
internal:通過if_seq_no和if_primary_term控制,判斷相等才索引
external:通過version判斷,大于或者不存在才索引
external_gte:通過version判斷,大于等于或不存在才索引
樂觀鎖控制并發:
es是分布式的,當文檔建立、更新或者删除時,必須将文檔新的版本号複制到叢集其他節點。es也是異步并發的,這意味着這些複制請求并行發送,并可能會亂序到達目标節點。es需要一種方法來保證文檔的就把按本不會覆寫新版本。
為了確定文檔的舊版本不會覆寫新版本,對文檔的每個操作都會由執行該操作的主分片配置設定一個序列号(_seq_no)。每次操作都會增加序列号,是以可以保證新操作比舊操作具有更高的序列号。這樣es可以通過操作的
_seq_no
確定新的文檔版本永遠不會被配置設定了較小序列号的更改覆寫。
在PUT資料是會生成初始的
_seq_no
_primary_term
:_seq_no針對索引級别,不同文檔id的_seq_no會和并累加計算。
POST caster/_doc/2
{
"name":"2"
}
{
"_index" : "caster",
"_type" : "_doc",
"_id" : "2",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 6,
"_primary_term" : 1
}
Get API可以直接擷取
_seq_no
_primary_term
,Search API需要指定
seq_no_primary_term
參數顯示他們。
_seq_no
_primary_term
唯一地辨別更改。通過記錄傳回的_seq_no和_primary_term,您可以確定僅在檢索後沒有對其進行其他更改的情況下才更改文檔。通過設定index、update 或delete API的
if_seq_no
if_primary_term
參數來完成的。
version和seq_no&primary_term的差別:
version應用于外部即version_type=external時進行控制;
新版本使用seq_no&primary_term應用于es内部自己版本控制時使用。
primary_term的意義:
在shard節點間遷移,修改副本數等情況均未發生改變。
重新配置設定選舉主shard或者主shard當機副本上位時多個文檔_seq_no一樣等異常時起作用。