1. Concurrency conflicts

Multiple threads access a piece of data in ES at the same time, and then modify it and update it to ES. Due to the different sequence of threads, the subsequent modification may overwrite the previous modification. Obviously, such concurrent conflict is not allowed in some scenarios, such as the modification of e-commerce commodity inventory.

As shown, when two users at the same time order for milk powder, two threads at the same time to read the milk powder on current inventory, read the inventory quantity is 100, when A thread A and B at the same time deduct stock 1, when two users under the single, milk powder, the rest of the overall inventory is 99, actually should be 98, due to no locking control concurrent access to inventory quantity is not allowed.

2. Optimistic locking

Commercial milk powder stock 100 pieces. Optimistic locks are unlocked, and each thread can do whatever it wants. So the inventory is 100 and the inventory after user A buys the product is minus 1, so the inventory is 99. At this point, user B also submitted the order, but user B’s thread carried an inventory of 100 pieces. In the optimistic lock state, user B will check whether the version number of this data in ES is consistent with its own. If it is inconsistent, user B will not submit the data, and will go to ES to obtain the latest 99 pieces of data, which will be reduced by one again and become 98. Then follow the above process to write.

Advantages: High concurrency, no data lock, a large number of concurrent operation threads

Disadvantages: Each update requires a comparison of the version number, and may need to reload the data, modify it again, and then write; This process may be repeated several times

3. The pessimistic locking

Every time I go to get the data, I think someone else will change it, so every time I go to get the data, I lock it, so that someone else will try to get the data and it will block until it gets the lock. Traditional relational database inside used a lot of this locking mechanism, such as row lock, table lock, read lock, write lock, etc., are in the operation before the first lock.

Common in relational databases, such as mysql inventory of 100 items. When user A reads milk powder data, the database line will be locked at the same time, and when user B also reads milk powder data, it will be locked out and in the waiting state. The lock is released only when user A buys the item and inventory -1. At this point, user B can move all of a sudden. At this time, the inventory of goods acquired by user B is 99. After user B buys the goods, the inventory becomes 98.

The control scheme for pessimistic locking is that in any case, the lock is locked, and then only one thread can manipulate the data. Of course, different scenarios have different locks, such as table – level locks, row – level locks, read – level locks, and write – level locks.

Advantages: convenient, direct lock, transparent to the program, do not need to do additional operations

Disadvantages: Low concurrency, only one thread can manipulate data at a time

4. How to implement optimistic lock concurrency control within Elasticsearch based on _version

_version metadata

PUT my_index001/_doc/4 {"name":" milk powder ", "dec":" juvenile milk powder ", "price":250, "producer":" juvenile milk powder ", "Tags" : [" young ", "calcium"]} {" _index ":" my_index001 ", "_type" : "_doc", "_id" : "4", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 23, "_primary_term" : 1 }Copy the code

The first time you create a document, its _version internal number is 1; In the future, every time the document is modified or deleted, the _version version number will be automatically incremented by 1; Even if deleted, the version number of the data will be increased by one

DELETE my_index001/_doc/4

{
  "_index" : "my_index001",
  "_type" : "_doc",
  "_id" : "4",
  "_version" : 2,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 24,
  "_primary_term" : 1
}
Copy the code

We will find that after deleting a document, we can prove from one side that it is not physically deleted immediately, because some of its version number and other information remains. Deleting a document and then recreating the document will actually add 1 to the delete version number

PUT my_index001/_doc/4 {"name":" milk powder ", "dec":" juvenile milk powder ", "price":250, "producer":" juvenile milk powder ", "Tags" : [" young ", "calcium"]} {" _index ":" my_index001 ", "_type" : "_doc", "_id" : "4", "_version" : 4, "result" : "created", "_shards" : { "total" : 2, "successful" : 1, "failed" : 0 }, "_seq_no" : 28, "_primary_term" : 1 }Copy the code