Redis pessimistic lock solves the problem of high concurrency grabbing red envelopes

Pessimistic locking is a method of using the lock provided by the internal mechanism of the database, that is, locking the updated data, so that once a transaction holds the lock of the database record during concurrency, other threads will no longer be able to update the data Yes, this is how pessimistic locking is implemented.

First, add a SQL with the id getRedPacketForUpdate in RedPacket.xml, and modify it to the following code:

<!-- 查询红包具体信息 -->
<select id="getRedPacketForUpdate" parameterType="long"
    resultType="com.pojo.RedPacket">
    select id, user_id as userId, amount, send_date as sendDate, total,
        unit_amount as unitAmount, stock, version, note from T_RED_PACKET
        where id =#{id} for update
</select>

Note that the for update statement added in SQL means that the row update lock on the database record will be held (because the primary key query is used here, only the row will be locked. If you are using a non-primary key query, you should consider whether to The problem of table locking may cause other queries to be blocked after locking), which means that in a high-concurrency scenario, only when a transaction holds the update lock can it continue to operate. If other threads want to update this Records need to wait, so that there will be no data consistency problems caused by the over-discovery phenomenon.

Then insert a new record into the database, as shown in the following code.

insert into `t_red_packet`(`id`,`user_id`,`amount`,`send_date`,`total`,`unit_amount`,`stock`,`version`,`note`) values ​​(1,1,'
200000.00 ','2019-07-29 16:35:20',20000,'10',20000,0,'200,000 yuan, 20,000 small red envelopes, 10 yuan each');

Still take 200,000 yuan of red envelopes, 10 yuan each, a total of 20,000 red envelopes as an example. After inserting this piece of data, get its number, and add the corresponding query method in RedPacketDao.

/**
  * Use the for update statement to lock
  *
  * @param id red packet id
  * @return red packet information
  */
public RedPacket getRedPacketForUpdate(Long id);

Next, modify the code of "RedPacket redPacket = redPacketDao.getRedPacket(redPacketId);" in the code of UserRedPacketServiceImpl to the following code:

Redpacket redpacket = redpacketDao.getRedPacketForUpdate(redpacketId);

After making these modifications, test again, you can get the results shown in Figure 1.
 


Figure 1 Pessimistic lock test results


The problem of oversending has been solved here, so the result is correct, which is very gratifying, but for the Internet, in addition to the correct result, we also need to consider performance issues. Let’s take a look at the test results first, as shown in Figure 2 shown.
 


Figure 2 Pessimistic lock performance test


Figure 2 shows that it took more than 100 seconds to complete the snatching of 20,000 red envelopes. Compared with the more than 10 seconds without locks, the performance has dropped a lot. You must know that only one lock is added to the database. When more locks are added, the performance of the database will continue to decline. Let’s discuss the performance degradation. s reason.

For pessimistic locking, when a thread preempts resources, other threads will not be able to obtain resources. At this time, the CPU will suspend these threads that cannot obtain resources, and the suspended threads will also consume CPU resources. Resources, especially in high concurrent requests, as shown in Figure 3.


Figure 3 High concurrency preempting resources


There can only be one transaction occupying the resource, and other transactions are suspended waiting for the transaction holding the resource to commit and release the resource. When thread 1 in the figure submits the transaction, the red envelope resource will be released, and at this time, thread 2, thread 3...thread n starts to grab resources. Here, it is assumed that thread 3 grabs resources, such as Figure 4 shows.


Figure 4 Multi-thread competition for resources and recovery


Once thread 1 commits the transaction, the lock will be released. At this time, the suspended thread will start to compete for red envelope resources, and the competing thread will be restored to the running state by the CPU and continue to run.

So it hangs up frequently, waiting for the thread holding the lock to release the resource. Once the resource is released, it starts to snatch it, restore the thread, and go round and round until all the red envelope resources are snatched up. Imagine that in the process of high concurrency, using pessimistic locks will cause a large number of threads to be suspended and resumed, which will consume a lot of resources, which is why the performance of pessimistic locks is not good.

Sometimes, we also refer to pessimistic locks as exclusive locks. After all, only one thread can monopolize this resource, or a blocking lock, because it will cause other threads to block. In any case, it will cause a decline in concurrency, which will cause the CPU to frequently switch thread contexts, resulting in low performance.

In order to overcome this problem, improve the concurrency capability, and prevent a large number of threads from being blocked and cause the CPU to perform a large number of context switches, programming masters proposed an optimistic locking mechanism, which has been widely used in enterprises.

Guess you like

Origin blog.csdn.net/unbelievevc/article/details/131673231