115 lines
4.0 KiB
Plaintext
115 lines
4.0 KiB
Plaintext
[[optimistic-concurrency-control]]
|
|
== Optimistic concurrency control
|
|
|
|
Elasticsearch is distributed. When documents are created, updated, or deleted,
|
|
the new version of the document has to be replicated to other nodes in the cluster.
|
|
Elasticsearch is also asynchronous and concurrent, meaning that these replication
|
|
requests are sent in parallel, and may arrive at their destination out of sequence.
|
|
Elasticsearch needs a way of ensuring that an older version of a document never
|
|
overwrites a newer version.
|
|
|
|
|
|
To ensure an older version of a document doesn't overwrite a newer version, every
|
|
operation performed to a document is assigned a sequence number by the primary
|
|
shard that coordinates that change. The sequence number is increased with each
|
|
operation and thus newer operations are guaranteed to have a higher sequence
|
|
number than older operations. Elasticsearch can then use the sequence number of
|
|
operations to make sure a newer document version is never overridden by
|
|
a change that has a smaller sequence number assigned to it.
|
|
|
|
For example, the following indexing command will create a document and assign it
|
|
an initial sequence number and primary term:
|
|
|
|
[source,js]
|
|
--------------------------------------------------
|
|
PUT products/_doc/1567
|
|
{
|
|
"product" : "r2d2",
|
|
"details" : "A resourceful astromech droid"
|
|
}
|
|
--------------------------------------------------
|
|
// CONSOLE
|
|
|
|
You can see the assigned sequence number and primary term in the
|
|
`_seq_no` and `_primary_term` fields of the response:
|
|
|
|
[source,js]
|
|
--------------------------------------------------
|
|
{
|
|
"_shards" : {
|
|
"total" : 2,
|
|
"failed" : 0,
|
|
"successful" : 1
|
|
},
|
|
"_index" : "products",
|
|
"_type" : "_doc",
|
|
"_id" : "1567",
|
|
"_version" : 1,
|
|
"_seq_no" : 362,
|
|
"_primary_term" : 2,
|
|
"result" : "created"
|
|
}
|
|
--------------------------------------------------
|
|
// TESTRESPONSE[s/"_seq_no" : \d+/"_seq_no" : $body._seq_no/ s/"_primary_term" : 2/"_primary_term" : $body._primary_term/]
|
|
|
|
|
|
Elasticsearch keeps tracks of the sequence number and primary term of the last
|
|
operation to have changed each of the documents it stores. The sequence number
|
|
and primary term are returned in the `_seq_no` and `_primary_term` fields in
|
|
the response of the <<docs-get,GET API>>:
|
|
|
|
[source,js]
|
|
--------------------------------------------------
|
|
GET products/_doc/1567
|
|
--------------------------------------------------
|
|
// CONSOLE
|
|
// TEST[continued]
|
|
|
|
returns:
|
|
|
|
[source,js]
|
|
--------------------------------------------------
|
|
{
|
|
"_index" : "products",
|
|
"_type" : "_doc",
|
|
"_id" : "1567",
|
|
"_version" : 1,
|
|
"_seq_no" : 362,
|
|
"_primary_term" : 2,
|
|
"found": true,
|
|
"_source" : {
|
|
"product" : "r2d2",
|
|
"details" : "A resourceful astromech droid"
|
|
}
|
|
}
|
|
--------------------------------------------------
|
|
// TESTRESPONSE[s/"_seq_no" : \d+/"_seq_no" : $body._seq_no/ s/"_primary_term" : 2/"_primary_term" : $body._primary_term/]
|
|
|
|
|
|
Note: The <<search-search,Search API>> can return the `_seq_no` and `_primary_term`
|
|
for each search hit by setting <<search-request-seq-no-primary-term,`seq_no_primary_term` parameter>>.
|
|
|
|
The sequence number and the primary term uniquely identify a change. By noting down
|
|
the sequence number and primary term returned, you can make sure to only change the
|
|
document if no other change was made to it since you retrieved it. This
|
|
is done by setting the `if_seq_no` and `if_primary_term` parameters of either the
|
|
<<docs-index_,Index API>> or the <<docs-delete,Delete API>>.
|
|
|
|
For example, the following indexing call will make sure to add a tag to the
|
|
document without losing any potential change to the description or an addition
|
|
of another tag by another API:
|
|
|
|
[source,js]
|
|
--------------------------------------------------
|
|
PUT products/_doc/1567?if_seq_no=362&if_primary_term=2
|
|
{
|
|
"product" : "r2d2",
|
|
"details" : "A resourceful astromech droid",
|
|
"tags": ["droid"]
|
|
}
|
|
--------------------------------------------------
|
|
// CONSOLE
|
|
// TEST[continued]
|
|
// TEST[catch: conflict]
|
|
|