As I said,
Elasticsearch is a distributed document store, we need to resolve conflicts
that come with concurrency in distributed application.
For example
Suppose we are maintaining our products information in elastics search. Every product has price, number of items available.
Suppose we are maintaining our products information in elastics search. Every product has price, number of items available.
GET xyz/products/1 { "_index": "xyz", "_type": "products", "_id": "1", "_version": 1, "found": true, "_source": { "price": "2560.19", "items_available": "132" } }
Lets say
there are two persons ‘A’ and ‘B’ want to purchase product 1 The sequence like
below.
1. A gets
information about product 1
"_source": {
"price": "2560.19",
"items_available":
"132"
}
2. B also
gets information about product 1
"_source": {
"price": "2560.19",
"items_available":
"132"
}
3. A
purchase product 1, decrement items_available by 1, and saves the document.
"_source": {
"price": "2560.19",
"items_available":
"131"
}
4. B purchase product 1, decrement
items_available by 1, and saves the document.
"_source": {
"price": "2560.19",
"items_available":
"131"
}
But
"items_available" should be 130 (since two purchases happened), but
it is 131.
How to solve this concurrency problem?
We can solve
this problem by using version number of the document. Whenever
somebody wants to update a document, they have to tell which version of the
document they are going to update, if that version is not current, request will
fail.
How to specify version number while updating?
By using
query parameter version.
PUT
/website/blog/1?version=1
following is the order purchase sequence using version number.
1. A gets current
document of product 1.
{
"_index": "xyz",
"_type": "products",
"_id": "1",
"_version": 1,
"found": true,
"_source": {
"price": "2560.19",
"items_available":
"132"
}
}
2. B also
gets current document of product 1.
{
"_index": "xyz",
"_type": "products",
"_id": "1",
"_version": 1,
"found": true,
"_source": {
"price": "2560.19",
"items_available":
"132"
}
}
3. A
purchase product 1, sends the update request by specifying version number.
PUT
xyz/products/1?version=1
{
"price": "2560.19",
"items_available": "131"
}
4. B purchase product 1, sends the update
request by specifying version number. Since B is trying to update older version
of the document, B gets VersionConflictEngineException.
PUT
xyz/products/1?version=1
{
"price": "2560.19",
"items_available": "131"
}
When B
submits above request, it gets following response.
{
"error": "VersionConflictEngineException[[xyz][2]
[products][1]: version conflict, current [2], provided [1]]",
"status": 409
}
At
application side you can take decision when VersionConflictEngineException
happens. Suppose, for our application, if we got VersionConflictEngineException,
we read the latest document again and decrease the items_available by 1. If
items_available is 0, we simply send response, “Items Out Of stock”.
No comments:
Post a Comment