欢迎访问 夜阑小雨 我的学习碎片档案,这里记录了我的学习内容和工作中经验,希望给您带去帮助。

php+redis秒杀实现

PHP 夜阑小雨 29℃ 0评论

秒杀是一个非常考验性能的业务场景

如果按照我们日常逻辑实现,总会出现超卖的现象。

那么如何保证系统的稳定性和数据的正确性。

一、日常下单扣库存模式:

以下代码是一遍情况下的下单逻辑:

<?php  
$error_level = error_reporting(0);
$con = new mysqli('localhost','root','root','test');
if(!$con){
    echo "数据库连接失败";
}
$sql = "select * from products where id=1";
$result = mysqli_query($con,$sql);
$aa= mysqli_fetch_row($result);
if($aa[3]>0){

    sleep(1);

    $sql = "update products set store=store-1 where id=1";

    if(mysqli_query($con,$sql)){

        echo "更新成功";
    }

}else{
    echo "没有库存";
}

这里使用 ab压测去执行,会发现库存都会成为负数。

二、通过redis去实现秒杀的业务前置拦截。

我们这里主要考虑秒杀抢购前先扣库存,如果库存足够再走下单流程,如果不够直接结束活动

我们这里是有redis的事务去处理具体如下:

<?php
 
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$store = 10;  // 当前商品秒杀的库存数, 设置->存储本地,不能读库 
// 监视销量  虚拟库存
$redis->watch('sales'); // 监视作用,key不存在 默认创建为0

$salse = $redis->get('sales'); //获取销量

var_dump($salse);

// 当秒杀结束后要开始另一个秒杀活动时将sales 置空,不然销量依然是10
// $redis->del('sales');
// exit();

if ($salse>=$store) {
     exit("秒杀已经结束!");
}

// 开启事务处理

$redis->multi();
$redis->incr('sales');//增加销量

$res = $redis->exec();//提交事务  成功 1 失败 0

if($res){
    // 提交成 开始更改库存 下订单
    include "db.php";
    $sql  = "update products set  store = store -1  where id =1";
    if ($mod->query($sql)) {
        echo "库存更新成功!";         
    }
}else{
    //事务提交失败不减库存
    exit("失败");
}

这里使用 ab压测去执行,会发现库存都一直会为0。

这里需要注意的是“sales”在一场秒杀活动结束之后一定要置空,不然会一直秒杀结束。

转载请注明:夜阑小雨 » php+redis秒杀实现

喜欢 (1)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址