Elasticsearch Series --- and optimistic locking concurrency control implementation principles

Overview

This part describes the implementation principle about the optimistic concurrency control and locking Elasticsearch, citing common electricity business scene, relational database concurrency control, ES concurrency control practices.

Concurrency scenarios

Whether relational database application, or do a search using Elasticsearch accelerate the scene, as long as the data is updated, concurrency control is the eternal subject.

When we use the ES updated document, first read the original document, make changes, and then re-index the document, if there is more than one person doing the same operation, not concurrency control, then it is likely to occur amend loss . Some scenes may be lost twelve data does not matter (such as the number of articles read statistics, the number of comments statistics), but some scenes stringent requirements for extremely high data loss could result in a very serious production problems, such as electrical goods business system the number of stocks, lost the next update may cause the phenomenon oversold.

We were still under the single-link business systems, for example, an item inventory 100, down two single-user purchase, contain this product, implementation steps conventional single buckle stock

  1. The client fulfill orders data validation, ready to execute the next single transaction.
  2. Client obtains the number of stock merchandise from ES.
  3. Client submits the order transaction and deduct inventory number.
  4. The client updated the number of inventory write back to ES.

Example flowchart follows:

Examples inventory update

If there is no concurrency control, inventory, this product will be updated to 99 (actually the correct value is 98), which would lead to oversold. Assume that the first step in the implementation of http-1 ratio http-2, the cause of this problem is the http-2 at the time of acquisition inventory data, at http-1 has not yet completed a single deduction of inventory, update the link to the ES, resulting in http-2 acquired data is already outdated data, subsequent updates and certainly wrong.

The above scenario, if an update more frequently, more concurrent read to update the longer this period of time consuming, the greater the probability of data error.

Common locking scheme

Concurrency control is particularly important, there are two common solutions to ensure the correctness of the data when concurrent updates.

Pessimistic concurrency control

Meaning pessimistic locking: I think that each update might have a conflict, concurrent updates of this operation is particularly tricky, I believe only in strict accordance with the definition of the size of my serial update, is the most secure, a thread updates time, waiting for the other thread, a thread before and after the update is complete, and then on the next thread.

Relational databases are widely used in the scheme, common table locks, row locks, read locks, write locks, or rely redis memcache, distributed lock implementation, are all areas of pessimistic locking. Obvious feature is the subsequent waiting thread is suspended, relatively low performance in general, but to achieve the self-locking distributed, particle size can be self-controlled (by rows, by customer, by business type, etc.), data correctness concurrent with the performance but also find a good compromise.

Optimistic concurrency control

Optimistic locking meanings: I think that the conflict does not happen often, I want to improve the performance of concurrent, should there be a conflict, the conflict of the thread is re-try a few times just fine.

In applications using relational databases, and often self-realization optimistic locking scheme, there are performance advantages, the program is not difficult to achieve, it is still very attractive.

Elasticsearch default is optimistic locking scheme, _version fields described earlier, the recording is updated each time the version number, only to get the latest update version number to update is successful, the other to get stale data update failure by the client program determines after the failure processing program, generally try again.

ES optimistic locking scheme

We were still above cases as the background, if the http-2 to submit updated data to the ES, ES will determine the version number of submitted over the current document version, document version number monotonically increasing, version number, if submitted over than the document version number small, then the data is expired, an error will update request, the procedure is as follows:

There are examples inventory update concurrency control

Use real optimistic locking control effect built _version

Our simulation platform on kibana two threads modify the same document data, open two browser tabs can we use the original case data:

{
  "_index": "music",
  "_type": "children",
  "_id": "2",
  "_version": 2,
  "found": true,
  "_source": {
    "name": "wake me, shark me",
    "content": "don't let me sleep too late, gonna get up brightly early in the morning",
    "language": "english",
    "length": "55"
  }
}

The current version is 2, we use a browser tab, issuing an update request, the current version to bring:

POST /music/children/2?version=2
{
 "doc": {
   "length": 56
 }
}

At this time, the update is successful

{
  "_index": "music",
  "_type": "children",
  "_id": "2",
  "_version": 3,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 2,
  "_primary_term": 2
}

At the same time we are on another tab, use the updated version = 2, erroneous results are as follows:

{
  "error": {
    "root_cause": [
      {
        "type": "version_conflict_engine_exception",
        "reason": "[children][2]: version conflict, current version [3] is different than the one provided [2]",
        "index_uuid": "9759yb44TFuJSejo6boy4A",
        "shard": "2",
        "index": "music"
      }
    ],
    "type": "version_conflict_engine_exception",
    "reason": "[children][2]: version conflict, current version [3] is different than the one provided [2]",
    "index_uuid": "9759yb44TFuJSejo6boy4A",
    "shard": "2",
    "index": "music"
  },
  "status": 409
}

The key error message: version_conflict_engine_exception, version conflict, will rise to 3 version, the simulation failed retries, this time the update was successful.

The real scene, the number of retries with the relevant number of concurrent threads, more threads, more frequent updates, you might need to retry many times it may be updated successfully.

Use real optimistic lock control results outside _version

ES允许不使用内置的version进行版本控制,可以自定义使用外部的version,例如常见的使用Elasticsearch做数据查询加速的经典方案,关系型数据库作为主数据库,然后使用Elasticsearch做搜索数据,主数据会同步数据到Elasticsearch中,而主数据库并发控制,本身就是使用的乐观锁机制,有自己的一套version生成机制,数据同步到ES那里时,直接使用更方便。

请求语法上加上version_type参数即可:

POST /music/children/2?version=2&version_type=external
{
 "doc": {
   "length": 56
 }
}
唯一的区别
  • 内置_version,只有当你提供的version与es中的_version完全一样的时候,才可以进行更新,否则报错;
  • 外部_version,只有当你提供的version比es中的_version大的时候,才能完成修改。

Replica Shard数据同步并发控制

在Elasticsearch内部,每当primary shard收到新的数据时,都需要向replica shard进行数据同步,这种同步请求特别多,并且是异步的。如果同一个document进行了多次修改,Shard同步的请求是无序的,可能会出现"后发先至"的情况,如果没有任何的并发控制机制,那结果将无法相像。

Shard的数据同步也是基于内置的_version进行乐观锁并发控制的。

例如Java客户端向Elasticsearch某条document发起更新请求,共发出3次,Java端有严谨的并发请求控制,在ElasticSearch的primary shard中写入的结果是正确的,但Elasticsearch内部数据启动同步时,顺序不能保证都是先到先得,情况可能是这样,第三次更新请求比第二次更新请求先到,如下图:

Concurrency control example of an internal update ES

如果Elasticsearch内部没有并发的控制,这个document在replica的结果可能是text2,并且与primary shard的值不一致,这样肯定错了。

The order should be expected to update text1 -> text2 -> text3, the final result is correct text3. How that internal Elasticsearch do it?

Internal Elasticsearch when updating the document, will compare the version, if the requested version and document the version equal, do the update, if the document's version is already larger than the requested version, the description for this data has been back to the thread updated, and this discards the current request, the final result is text3.
At this time, the update order text1 -> text3, the end result is right.

summary

This part describes the reason for the confusion of data concurrency scenarios appear optimistic concurrency control when the lock Elasticsearch real principle, and ES internal data synchronization, incorrect place or detailed place, please notify modify, thank you.

High focus on Java concurrency, distributed architecture, more dry goods share technology and experience, please pay attention to the public number: Java Architecture Community
Java Architecture Community

Guess you like

Origin www.cnblogs.com/huangying2124/p/11986897.html
Recommended