当前位置:网站首页>Php+redis realizes the function of canceling orders over time

Php+redis realizes the function of canceling orders over time

2022-07-06 19:04:00 Student Li

Business scenario : Second kill case

Second kill business logic : Multiple users rush orders at the same time , adopt mysql The user who gets the row lock enters the page to be paid ( count down ). When the user fails to pay the order and times out, the order will be canceled and the inventory will be returned .

application

thinkphp+redis+workerman( You can customize the command resident )

1、thinkphp install workerman. It's just over here ,thinkphp Find the manual .

2、 Install well redis And expansion . Use the pagoda directly to finish , too .

3、 producer : Users create orders to redis Insert an order data .

$redis = new \Redis();
$redis->connect('127.0.0.1',6379);
//$redis->auth(' password ');//redis If you have a password, add 
/**
*seckill_time Is the queue name 
*time() + $seckill['pay_time'] Is the expiration timestamp 
*$newSeckillOrder->id For the order id, Sure json String store 
*/
$redis->zAdd('seckill_time', time() + $seckill['pay_time'], $newSeckillOrder->id);

4、 consumer : Here we need a resident memory to always query whether there is any message in the queue , If you have it, consume it .

workerman


/**
 *  Every process starts 
 * @param $worker
 */
public function onWorkerStart($worker)
{
    // Prevent time problems 
    date_default_timezone_set('PRC');

    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);
    //redis password 
    //$redis->auth(' password ');//redis Add this sentence if you have a password 

    if($worker->id === 0){
            // Other tasks 
    }
        // Second kill processing process 
    if($worker->id === 1){
        echo " Start the second kill task !\n";
        //workerman Timer , Once a second .
        Timer::add(1, function() use($redis) {
        // adopt zRangeByScore Inquire about seckill_time In line 0 Data to the current timestamp .
        $res = $redis->zRangeByScore('seckill_time', 0, time());
        // There is data 
        if (count($res) > 0) {
            foreach ($res as $k=>$v){
            // Process orders ,$res[$k] Orders deposited for producers id Or data .
            //.....
            // Consume row data in the queue 
             $redis->zRem('seckill_time', $res[$k]);
             }
            // Needless to say, I understand this step ! After all, resident memory , We should manage the memory well ~
            unset($res);
         }
    });
   }
}

test result :

My side is delay 20 Second consumption

as follows :

  After consumption, the queue will be empty ~

The reason for using this scheme :

Maybe some people will ask ,workerman With timer , You can delay the operation directly ? Why is it so unnecessary ?

The reason is simple , If workerman Suddenly something went wrong , Does some data delayed by the timer terminate ? This will cause the lost data to be unable to close the order ! So using redis Delay message queuing , Store data redis in , Even if workerman Something went wrong , Restart workerman You can also consume data that is not consumed !

About redis The problem of data loss during restart requires modifying the configuration as follows .

 find appendonly no  Change it to  appendonly yes find appendfsync  Set to  appendfsync everysec

solve redis The problem of losing data after restarting .

Of course, other message oriented middleware can also be used to solve , such as mq, However, the introduction of pagoda user installation is still redis Well !

remember ! Don't use the timer to check the database repeatedly ! Don't use the timer to check the database repeatedly ! Don't use the timer to check the database repeatedly !

Say it three times , The database is under great pressure ~

Of course, this scheme is also applicable to the automatic closing of the group when the group is due , You can make up your brain by yourself .

原网站

版权声明
本文为[Student Li]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/187/202207061111350571.html