Concurrent inventory reduction

There are many scenes of second kill, such as rush buying, ticket grabbing, red envelope grabbing, etc. In short, there are a lot of requests in a very short time.

As we all know, the general direction of this system design is flow restriction, that is, through layer by layer filtering, only relatively few requests will enter the core business processing layer.

Not to mention the second kill design and the use of queues to serialize requests, but to talk about how to use locks to ensure correct data, that is, it has reached the step of reducing inventory. In this step, if you ensure that you do not oversold.

If queues are used, they can be Java automatic queues or redis lpush rpop

The focus is on deducting inventory

I understand that the main way is to lock. Locking has two levels: one is the program level, the other is the database level.

Distributed lock

In this scenario, few people should use Java's own locks (such as synchronized and lock), because they are only valid in the same JVM. If your application deploys multiple servers, you should use distributed locks.

For redis distributed locks, please refer to my previous article "simple implementation of redis based distributed locks"

In fact, adding a distributed lock here is to turn a multithreaded request into a single threaded request, because only one thread obtains the lock and executes at a time, and the rest are blocked.

One thing to note here is that there may be problems when you apply transactions. Please see the following code

Maybe someone will write like this. It looks good at first sight. It's no problem, but careful practice has proved that it is caused by the problem.

As we know, the default transaction isolation level of MySQL is repeatable-read

For transaction isolation levels, refer to MySQL transaction isolation levels

Under this isolation level, the data returned by multiple reads in the same transaction is the same

At the same time, the default propagation feature of spring declarative transactions is required

Spring declarative transaction is the best example of spring AOP. Spring implements the transaction through AOP proxy, that is, the transaction has been started before calling the reducestock () method.

Then, in the case of concurrency, it may exist. Suppose that threads T1 and T2 execute here, so they both start transactions S1 and S2. T1 executes first and T2 executes later,

Since the transaction has been created when T2 executes, according to the isolation level, transaction S2 cannot read the committed data of S1 at this time, so the values read by T1 and T2 are the same, that is, T2 reads the inventory data before T1 update.

You can write your own code to test this. Here is a reference:

In view of this situation, we can put the inventory into redis and directly read and write to redis, so as to avoid being affected by database transactions. Of course, this will also bring new problems and will not be discussed.

Database optimistic lock

CAS (compare and swap)

In Java, if a thread wants to modify the value of a variable, the first step is to read the value of the variable from main memory to its own working memory, modify it, and finally write it back to main memory. This process can be summarized as read modify write. When writing back to memory, the value in the current memory may have changed. If you continue to write at this time, other people's data will be overwritten. You can write only when the value in memory is the same as the value read before it is modified. This is the same as the database. In Java, it is implemented through a method class such as compareandswapobject in unsafe, which directly calls CPU instructions.

There is also CAS in the database. Optimistic lock is a CAS

Classic optimistic lock implementation:

Adding a version ID to the data is generally realized by adding a numeric "version" field to the database table. When reading data, read out the value of the version field together. Each time the data is updated, add one to the version value. When we submit the update, we judge that the current version information of the corresponding record of the database table is compared with the version value obtained for the first time. If the current version number of the database table is equal to the version value obtained for the first time, it will be updated, otherwise it will be considered as expired data.

The version number will be brought when updating. Only when the current version number is consistent with the version queried before updating will it be updated

ABA problem

By the way, ABA in CAS

Suppose that the original value is a and thread-1 reads a and wants to change it to D, but during this period, other threads may have modified this value many times, but finally when thread-1 is ready to change a to D, it finds that it happens to be a and thinks no one has changed it. In fact, at this time, a is not the original a.

In other words, despite the comparison before modification, of course, the following situations will still occur:

Cause

The reason for the ABA problem is that only the "value" is verified in the CAS process. In some cases, although the "value" is the same, it is no longer the original data.

Optimization direction

CAS can not only compare "values", but also ensure that the original data is used for successful modification.

Common practice

For the comparison of "version number", one data version after another. If the version changes, even if the value is the same, it should not be modified successfully.

Focus not only on the value, but also on whether it is the original object

CAS optimistic lock based on "value" may cause ABA problem. For CAS optimistic locking, it must be ensured that "this data" is "that data" during modification. It should be compared by "value" and optimized to "version number".

reference resources

https://www.sohu.com/a/150900817_178889

https://blog.csdn.net/zhjunjun93/article/details/78560700

https://blog.csdn.net/rexct392358928/article/details/52230737

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>