Php+redis+锁机制实现高并发秒杀抢购解决方案

一、加排它锁

<?php   
$pdo=new PDO("mysql:dbname=demo;host=localhost","root","root");
$pdo->query('SET NAMES utf8');
$redis=new Redis();
$redis->connect('127.0.0.1', 6379); 
$num=$redis->get("num");
if($num<=12)//假定库存只有12个
{   
sleep(2);
$sql = "select * from goods where id=1 for update";
$stmt = $pdo->query($sql);
$res=$stmt->fetch(2);
if($res['num'])
{   $redis->incr('num');
    $stmt = $pdo->exec("update goods set num=num-1 where id=1");
//自行写各种业务处理。。。
}
   
}
else{
    echo "抢购结束";
}

二、php+redis乐观锁

<?php   
$pdo=new PDO("mysql:dbname=demo;host=localhost","root","root");
$pdo->query('SET NAMES utf8');
$redis=new Redis();
$redis->connect('127.0.0.1', 6379); 
$uid=md5(mt_rand(1,1000000));//模拟生成用户id
var_dump($redis->lrange('user',0,-1));

$num=$redis->get("num");
//  $redis->del("num");
//  $redis->del("user");
//die;
if($num>=3) exit("抢购结束");//假设只有3个库存量
$redis->watch('num');//监听key的变化,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断
//开始事务
$redis->multi(); 
$redis->incr('num'); 
sleep(2);
$result=$redis->exec(); //返回true表示执行成功,nil表示事务被中断

if($result)
{  
    $stmt = $pdo->exec("update goods set num=num-1 where id=1");
    if($stmt){
        echo "抢购成功";
        $redis->lpush("user",$uid);//记录抢购成功的用户id
        //自行写各种业务处理。。。

    
    }

}

经过ab压测后,就再也不会出现超卖的情况啦,哈哈

三、最后一个用文件锁,性能也是最低的,不推荐使用

<?php
$redis=new Redis();
$redis->connect('127.0.0.1',6379);
$num=$redis->get('num');//购买数量
$ku=1;//库存量
if($num<$ku){
$file=fopen('1.lock',"a");
if(flock($file,LOCK_EX))
{
$store=$redis->incr('num');
fwrite($file,$store);
sleep(5);
//自行写各种业务处理。。。
flock($file,LOCK_UN);

}
 
fclose($file);
 
}

猜你喜欢

转载自blog.csdn.net/qq_39418742/article/details/105974159