PHP concurrent deduction to ensure data consistency (pessimistic lock and optimistic lock)

Time:2020-11-28

Business scenario analysis

In the logic of purchasing goods, it is necessary to query and deduct the balance of the user‘s wallet

Exception: if the same user concurrently executes multiple services, there is a certain probability of data inconsistency in the “query + deduction” business

Tips: if there is no restriction on the frequency of single interface requests, users may have data inconsistency by using the means of concurrent requests

Deduction scenario

Step 1: query user wallet balance from database

SELECT balance FROM user_wallet WHERE uid = $uid;
+---------+
| balance |
+---------+
| 100     |
+---------+
1 row in set (0.02 sec)

Step 2: business logic

Tips: the article shares the logic of handling the same user’s concurrent deduction consistency and checking the inventory

1. Query commodity price, such as 70 yuan
2. Check whether the balance of commodity price comparison is enough, and deduct money when it is enough to submit the order logic

if(goodsPrice <= userBalance) {
    $newUserBalance = userBalance - goodsPrice;  
}else {
    Throw new userwalletexception (['msg '= >'insufficient user balance');
}

Step 3: modify the balance of the database

UPDATE user_wallet SET balance=$newUserBalance WHERE uid = $uid

In the case of no concurrency, there is no problem in this process. The original balance is 100 yuan, and the purchase of goods is 70 yuan, and the remaining 30 yuan

Abnormal scene

Step 1: a certain probability for users to simultaneously purchase business a and service B (different instances / services)parallelThe query balance is 100

PHP concurrent deduction to ensure data consistency (pessimistic lock and optimistic lock)

Step 2: business a and business B deduct money logically, business a commodity 70 result balance 30, business B commodity 80 result balance 20

PHP concurrent deduction to ensure data consistency (pessimistic lock and optimistic lock)

Step3:

1. Business a is modified first, and the modified balance is 30

PHP concurrent deduction to ensure data consistency (pessimistic lock and optimistic lock)

2 after business a, modify the balance to 20

PHP concurrent deduction to ensure data consistency (pessimistic lock and optimistic lock)

At this time, an exception appears. The original balance is 100 yuan, the total commodity price of business a and business B is 150 yuan (70 + 80), and the remaining balance is 20 yuan.

Outliers: business a and business BparallelThe query balance is 100

Solution

Pessimistic lock

Use redis pessimistic lock. For example, if you grab a key, you can continue the operation. Otherwise, the operation is prohibited

It encapsulates a redislock out of the box

<?php

use Ar414\RedisLock;

$redis = new \Redis();
$redis->connect('127.0.0.1','6379');

$lockTimeOut = 5;
$redisLock = new RedisLock($redis,$lockTimeOut);

$lockKey    = 'lock:user:wallet:uid:1001';
$lockExpire = $redisLock->getLock($lockKey);

if($lockExpire) {
    try {
        //select user wallet balance for uid
        $userBalance = 100;
        //select goods price for goods_id
        $goodsPrice = 80;

        if($userBalance >= $goodsPrice) {
            $newUserBalance = $userBalance - $goodsPrice;
            //TODO set user balance in db
        }else {
            throw new Exception('user balance insufficient');
        }
        $redisLock->releaseLock($lockKey,$lockExpire);
    } catch (\Throwable $throwable) {
        $redisLock->releaseLock($lockKey,$lockExpire);
        throw new Exception('Busy network');
    }
}

Optimistic lock

useCAS(Compare And Set)

When the set is written back, the condition of the initial state is addedcompareOnly when the initial state is unchanged, can set write back success and ensure data consistency

Will:

UPDATE user_wallet SET balance=$newUserBalance WHERE uid = $uid

Change to:

UPDATE user_wallet SET balance=$newUserBalance WHERE uid = $uid AND balance = $oldUserBalance

In this way, only one of the concurrent operations is successful, and the success is judged according to whether the affect rows is 1

epilogue

  • There are many solutions, and this is just one of them
  • Using redis pessimistic lock will reduce throughput

Recommended Today

Interviewer: young man, what do you think of the principle of distributed system

1 Concept 1.1 model 1.2 copies 1.3 indicators for measuring distributed systems 2. Principle of distributed system 2.1 data distribution 2.2 basic copy agreement 2.3 lease mechanism 2.4 quorum mechanism 2.5 log technology 2.6 two phase submission protocol 2.7 MVCC 2.8 Paxos protocol 2.9 CAP 1 Concept 1.1 model node In a specific project, a […]