当前位置:网站首页>What is optimistic lock and what is pessimistic lock

What is optimistic lock and what is pessimistic lock

2022-06-26 09:07:00 Shuai dada's structural road

original text

One 、 concurrency control

When... May appear in the program Concurrent situations , It is necessary to ensure the accuracy of data in the case of concurrency , This ensures that when the current user operates with other users , The result obtained is the same as when he operated alone . This is called concurrency control . The purpose of concurrency control is to ensure that the work of one user will not have an unreasonable impact on the work of another user .

No concurrency control , May lead to Dirty reading 、 Unreal and unrepeatable reading Other questions .

img

Concurrency control , Generally, it is related to database management system (DBMS) of . stay DBMS Concurrency control tasks in , This is to ensure that multiple transactions add, delete, modify and query the same data at the same time , Do not break the isolation of transactions 、 Consistency and database uniformity .

The main means to realize concurrency control are divided into optimistic concurrency control and pessimistic concurrency control .
Whether it is pessimistic lock or optimistic lock , It's all defined by people , It can be thought of as an idea . In fact, it is not only the concept of optimistic lock and pessimistic lock in relational database system , image hibernate、tair、memcache There are similar concepts . therefore , You shouldn't take an optimistic lock 、 Pessimistic locks are compared with other database locks . Optimistic lock is more suitable for the situation of reading more and writing less ( Read more scenes ), Pessimistic locking is more suitable for writing more and reading less ( Write more scenes ).

Two 、 Pessimistic locking (Pessimistic Lock)

1️⃣ understand
When you want to modify a piece of data in the database , To avoid being modified by others at the same time , The best way is to lock the data directly to prevent concurrency . With the help of database lock mechanism , Lock before modifying data , The way to modify it is called pessimistic concurrency control 【Pessimistic Concurrency Control, abbreviation “PCC”, also called “ Pessimistic locking ”】.

Pessimistic locking , With strong exclusivity and exclusivity . It refers to the data being exposed to the outside world ( Includes other current transactions of the system , And transactions from external systems ) The revision was conservative . therefore , In the whole data processing process , Lock the data . Pessimistic lock implementation , It often relies on the locking mechanism provided by the database ( Only the locking mechanism provided by the database layer can truly guarantee the exclusivity of data access , otherwise , Even in this system to implement the locking mechanism , There is no guarantee that external systems will not modify the data ).

img

It's called pessimistic lock , It's because it's a pessimistic concurrency control method for data modification . Always assume the worst , Every time the data is read, other threads will change the data by default , Therefore, locking operation is needed , When other threads want to access data , All need to block pending . Pessimistic lock implementation :

  1. Traditional relational databases use this locking mechanism , For example, line locks. 、 Table locks 、 Read the lock 、 Write locks, etc. , Lock before operation .
  2. Java The synchronization inside synchronized Keyword implementation .

2️⃣ Pessimistic locks are mainly divided into Shared lock and exclusive lock

  • Shared lock 【shared locks】 Also known as read lock , abbreviation S lock . seeing the name of a thing one thinks of its function , Shared lock is that multiple transactions can share a lock for the same data , All have access to data , But it can only be read but not modified .
  • Exclusive lock 【exclusive locks】 Also known as write lock , abbreviation X lock . seeing the name of a thing one thinks of its function , Exclusive locks are not allowed to coexist with other locks , If a transaction acquires an exclusive lock on a data row , Other transactions can no longer acquire other locks of the row , Including shared lock and exclusive lock . Transactions that acquire exclusive locks can read and modify data rows .

3️⃣ explain
Pessimistic concurrency control is actually “ Take the lock first and then visit ” A conservative strategy , For the security of data processing . But in terms of efficiency , The mechanism of dealing with lock will cause extra cost to the database , And increase the chance of deadlock . It also reduces parallelism , If a transaction locks a row of data , Other transactions must wait for the transaction to complete before they can process that row of data .

3、 ... and 、 Optimism lock (Optimistic Locking)

1️⃣ understand
Optimistic lock is relative to pessimistic lock , Optimistic locking assumes that data generally does not cause conflict , So when the data is submitted for update , The data conflict will be formally detected or not , If conflict , The exception information is returned to the user , Let the user decide how to do it . Optimistic lock is suitable for reading more and writing less , This can improve the throughput of the program .

img

Optimistic lock adopts a more relaxed locking mechanism . Also to avoid database unreal reading 、 A mechanism that causes data processing errors due to long service processing time , But optimistic locks do not deliberately use the lock mechanism of the database itself , It's based on the data itself to ensure the correctness of the data . The realization of optimistic lock :

  1. CAS Realization :Java in java.util.concurrent.atomic The atomic variables under the package use an optimistic lock CAS Realization way .
  2. Version number control : Generally, a data version number is added to the data table version Field , Indicates the number of times the data has been modified . When the data is modified ,version Value meeting +1. When a thread A To update data , Read data at the same time version value , When you submit an update , If I just read version The value is the same as that in the current database version Update when values are equal , Otherwise, retry the update operation , Until the update is successful .

2️⃣ explain
Optimistic concurrency control believes in data competition between transactions (data race) The probability is relatively small , So go as straight as you can , Don't lock until you submit , So there won't be any locks and deadlocks .

Four 、 Concrete realization

1️⃣ Pessimistic lock implementation
Pessimistic lock implementation , It often relies on the locking mechanism provided by the database . In the database , The process of pessimistic lock is as follows :

  1. Before making changes to the record , First try to lock the record (exclusive locks).
  2. If locking fails , Indicates that the record is being modified , Then the current query may have to wait or throw an exception . The specific response mode is determined by the developer according to the actual needs .
  3. If you lock successfully , Then you can make changes to the records , Business When it's done, it'll unlock .
  4. During this period, if there are other operations to modify or add exclusive locks to the record , Will wait to unlock or throw an exception directly .

With MySql Innodb engine give an example , explain SQL Application of pessimistic lock in

Use pessimistic locks , Must close MySQL Auto-commit properties for the database set autocommit=0. because MySQL By default autocommit Pattern , in other words , When an update operation is performed ,MySQL The results will be submitted immediately .

Explain the use of pessimism lock with the process of deducting inventory under E-Commerce orders :

img

In the face of id = 1 Before the modification of the records , Through the first for update The way to lock , And then make changes . This is a typical pessimistic lock strategy .

If concurrency occurs , At the same time, only one thread can start a transaction and get id=1 Lock of , Other transactions must wait until this transaction is committed . This ensures that the current data will not be modified by other transactions .

Use select…for update Lock data , Pay attention to the level of lock ,MySQL InnoDB Default row level lock . Row level locks are all index based , If one SQL Statement without index will not use row level lock , Can use watch level lock to lock the whole watch , This is something to be aware of .

2️⃣ Optimistic lock implementation Optimistic locking does not need the help of database locking mechanism

There are two main steps : Conflict detection and data update . The typical thing is CAS (Compare and Swap).

CAS Compare and exchange . It is a mechanism to solve the performance loss caused by using lock in multithreading parallel ,CAS An operation contains three operands —— Memory location (V)、 The original value of the expected (A) And the new value (B). If the value of the memory location (V) With the expected original value (A) Match , The processor will automatically update the location value to the new value (B). otherwise , The processor does nothing . In either case , It will be in CAS Command to return the value of the location before .CAS Well, that's valid “ Student: I think location (V) Should contain values (A). If the value is included , The new value (B) Put it in this position ; otherwise , Do not change the location , Just tell me the current value of this position ”.Java in ,sun.misc.Unsafe Class provides hardware level atomic operations to implement this CAS.java.util.concurrent A large number of classes under the package use this Unsafe.java Class CAS operation .

When multiple threads are trying to use CAS When updating the same variable at the same time , Only one of the threads can update the value of the variable , All other threads fail , Failed threads are not suspended , They were told they had lost the competition , And try again . For example, the stock deduction problem in front , Through optimistic locking, you can achieve the following :

img

Optimistic lock use

Before the update , First, query the current inventory in the inventory table (quantity), And then doing update When , Take inventory as a modification condition . When submitting updates , Judge that the current inventory number recorded in the database table is compared with the inventory number retrieved for the first time , If the current inventory in the database table is the same as that in the first retrieval , Is updated , Otherwise, it is considered to be outdated data .

There is a serious problem with the above UPDATE statement , namely ABA problem img

  1. For example, as soon as the thread fetches the stock out from the database 3, At this time, thread 2 also fetches the stock out from the database 3, And thread 2 performs some operations and becomes 2.
  2. Then thread 2 changes the inventory number to 3, At this time, as soon as the thread proceeds CAS Operation discovery database is still 3, Then the thread operates successfully .
  3. Although thread one is CAS Successful operation , But it doesn't mean that there is no problem in this process .

A better solution , It is through a single one that can be incremented in sequence version Field . The optimization is as follows : img

Every time an optimistic lock performs a data modification operation , They all carry a version number , Once the version number is consistent with the version number of the data, the modification operation can be performed and the version number can be executed +1 operation , Otherwise, the execution fails . Because the version number of each operation will be increased , So it won't show up ABA problem . except version outside , You can also use time stamps , Because timestamps are naturally sequential .

above SQL In fact, there are still some problems , Is once you meet High concurrency When , Only one thread can be modified successfully , Then there will be a lot of failures . For e-commerce websites like Taobao , High concurrency is common , It's obviously unreasonable to always let users perceive failure . therefore , We still need to find ways to reduce the granularity of optimistic locks . A better suggestion , Is to reduce the strength of the optimistic lock , Maximize throughput , Improve concurrency ! as follows :

img

above SQL In the sentence , If the singular number of users is 1, Through quantity - 1 > 0 Optimistic lock control . In the process of execution , I'll look it up in an atomic operation quantity Value , And deduct it 1.

High concurrency environment Lock granularity Control is an important knowledge . Choose a good lock , In the case of data security , It can greatly improve the throughput , To improve performance .

5、 ... and 、 understand CAS Bottom

img

flow chart

If there are 3 One thread needs to be modified at the same time AtomicInteger Value , The underlying mechanism is as follows :

  1. First , Each thread gets the current value first , And then one atom CAS operation . That's what atoms mean CAS The operation must be completed by itself , No interruptions .
  2. then CAS In operation , Will compare , Whether the current value is the value just obtained . If it is , It means that no one has changed this value , Then set it to accumulate 1 The next value is .
  3. Empathy , If someone's doing it CAS When , It is found that the previously obtained value is different from the current value , It can lead to CAS Failure . After failure , Into an infinite loop , Get the value again , Then perform CAS operation .

6、 ... and 、CAS Typical applications

java.util.concurrent.atomic Most of the classes under the package use CAS Operation to achieve , such as AtomicInteger、AtomicBoolean、AtomicLong. Generally, when the competition is not particularly fierce , The atomic operation performance under this package is better than that of using synchronized Keyword is much more efficient ( see getAndSet(), If the competition for resources is very fierce , This for The loop may last a long time and fail to jump out . However, this situation may need to consider reducing resource competition ).
These atomic class operations may be used in many scenarios . A typical application is counting , In the case of multithreading, you need to consider Thread safety problem .

1️⃣ Support counting function Demo Realization

public class Increment {
    
    private int count = 0;
    public void add() {
    
        count++;
    }
}

In a concurrent environment count It's not safe to do autoincrement , Why not safe and how to solve this problem ?

2️⃣ Why in concurrent environment count Self increasing operation is not safe ? because count++ It's not an atomic operation , It's a combination of three atomic operations :

  1. Read Memory Medium count Value is assigned to a local variable temp;
  2. perform temp+1 operation ;
  3. take temp Assign a value to count.

So if two threads execute at the same time count++ Words , There is no guarantee that thread 1 will execute the above three steps in sequence before thread 2 starts to execute .

3️⃣ In a concurrent environment count++ Solutions to unsafe problems

programme ①:synchronized Lock . Only one thread can lock at the same time , Other threads need to wait for locks , So it won't show up count The problem of inaccurate counting :

public class Increment {
    
    private int count = 0;
    public synchronized void add() {
    
        count++;
    }
}

But introduce synchronized It will cause the problem of multiple threads queuing , It's equivalent to serializing each thread , Line up one by one 、 Lock 、 Processing data 、 Release the lock , Come in next . Only one thread executes at a time , Such a lock is a little “ heavyweight ” 了 . This is similar to the implementation of pessimistic lock , Need to get this resource , Just lock it , No other thread can access the resource , Until the lock on the resource is released after the operation . Though with Java Version update , Also on the synchronized A lot of optimization , But dealing with this simple accumulation operation , It still seems “ Is too heavy ”.

programme ②:Atomic Atomic classes . about count++ The operation of , You can do it another way ,Java And a series of Atomic Atomic classes , for instance AtomicInteger:

//import java.util.concurrent.atomic.AtomicInteger;
public static void main(String[] args) {
    
    public static AtomicInteger count = new AtomicInteger(0);
    public static void increase() {
    
        count.incrementAndGet();
    }
}

Multiple threads can execute concurrently AtomicInteger Of incrementAndGet(), It means putting count The sum of the values of 1, Then it returns the latest accumulated value . actually ,Atomic The underlying layer of atomic class is not a traditional locking mechanism , It's unlocked CAS Mechanism , adopt CAS Mechanism to ensure the security of multithreading to modify a value .

7、 ... and 、CAS performance optimization

As can be seen from the flow chart , A large number of threads modify one simultaneously AtomicInteger, There may be a lot of threads spinning around , Into a cycle of infinite repetition . These threads keep getting values , Then launch CAS operation , But I found that this value has been changed by others , So we go back to the next cycle , Get value , launch CAS The operation failed again , Go back to the next cycle . High concurrent updates in a large number of threads AtomicInteger When , This kind of problem may be more obvious , Result in a large number of thread empty loops , Self rotation , Performance and efficiency are not particularly good . So how to optimize ?

Java8 There is a new class ,LongAdder, It's just trying to use segmentation CAS And automatic segmented migration to greatly improve the multithreading and high concurrency execution CAS Performance of operation , How does this class optimize performance ? Pictured :

img

LongAdder

LongAdder The core idea is the separation of hot spots , This and ConcurrentHashMap Their design ideas are similar . Will be value Values are separated into an array , When multithreaded access , adopt hash The algorithm maps to one of the numbers for counting . And the end result , Is the sum and accumulation of these arrays . thus , This reduces the granularity of the lock .

LongAddr The siblings are as follows :

img

LongAdder Brothers

8、 ... and 、 How to choose

On the choice of optimistic lock and pessimistic lock , Mainly look at the difference between the two and the applicable scenarios .
1️⃣ Response efficiency : If you need a very high response speed , The optimistic lock scheme is recommended , Success is execution , Fail or fail , There is no need to wait for other concurrencies to release the lock . Optimistic locks are not really locked , Efficient . Once the granularity of lock is not well mastered , The probability of update failure will be higher , Prone to business failure .
2️⃣ Frequency of conflict : If the frequency of conflict is very high , Pessimistic lock is recommended , Guaranteed success rate . Conflicts are frequent , Choosing an optimistic lock will take many retries to succeed , It costs a lot .
3️⃣ Retry cost : If retrying is costly , Pessimistic lock is recommended . Pessimistic lock depends on database lock , Low efficiency . The probability of update failure is low .
4️⃣ Optimistic lock if someone updated it before you , Your update should be rejected , It allows users to re operate . Pessimistic lock will wait for the previous update to complete . That's the difference .

With the Internet Three high structure ( High concurrency 、 High performance 、 High availability ) The proposed , Pessimistic locks are less and less used in production environments , Especially in the business scenario with large concurrency .

MySQL Application of optimistic lock to e-commerce inventory concurrency

原网站

版权声明
本文为[Shuai dada's structural road]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/177/202206260835247536.html