OpenSearch/docs/reference/docs/concurrency-control.asciidoc
Boaz Leskes 52ba407931
Expose sequence number and primary terms in search responses (#37639)
Users may require the sequence number and primary terms to perform optimistic concurrency control operations. Currently, you can get the sequence number via the `docvalues_fields` API but the primary term is not accessible because it is maintained by the `SeqNoFieldMapper` and the infrastructure can't find it. 

This commit adds a dedicated sub fetch phase to return both numbers that is connected to a new `seq_no_primary_term` parameter.
2019-01-23 09:01:58 +01:00

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
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 of the last
operation to have changed each of the document 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]