php结合redis实现秒杀功能

<?php
第一种,简单实现
$conn =mysql_connect( "localhost" , "big" , "123456" );
if (! $conn ){
     echo "connect failed" ;
     exit ;
}
mysql_select_db( "big" , $conn );
mysql_query( "set names utf8" );
 
$price =10;
$user_id =1;
$goods_id =1;
$sku_id =11;
$number =1;
 
//生成唯一订单
function build_order_no(){
   return date ( 'ymd' ). substr (implode(NULL, array_map ( 'ord' , str_split ( substr (uniqid(), 7, 13), 1))), 0, 8);
}
//记录日志
function insertLog( $event , $type =0){
     global $conn ;
     $sql ="insert into ih_log(event,type)
     values( '$event' , '$type' )";
     mysql_query( $sql , $conn );
}
 
//模拟下单操作
//库存是否大于0
$sql = "select number from ih_store where goods_id='$goods_id' and sku_id='$sku_id'" ; //解锁 此时ih_store数据中goods_id='$goods_id' and sku_id='$sku_id' 的数据被锁住(注3),其它事务必须等待此次事务 提交后才能执行
$rs =mysql_query( $sql , $conn );
$row =mysql_fetch_assoc( $rs );
if ( $row [ 'number' ]>0){ //高并发下会导致超卖
     $order_sn =build_order_no();
     //生成订单
     $sql ="insert into ih_order(order_sn,user_id,goods_id,sku_id,price)
     values( '$order_sn' , '$user_id' , '$goods_id' , '$sku_id' , '$price' )";
     $order_rs =mysql_query( $sql , $conn );
     
     //库存减少
     $sql = "update ih_store set number=number-{$number} where sku_id='$sku_id'" ;
     $store_rs =mysql_query( $sql , $conn );
     if (mysql_affected_rows()){
         insertLog( '库存减少成功' );
     } else {
         insertLog( '库存减少失败' );
     }
} else {
     insertLog( '库存不够' );
}
?>.
第二种,使用mysql锁行的方式
 
<?php
$conn =mysql_connect( "localhost" , "big" , "123456" );
if (! $conn ){
     echo "connect failed" ;
     exit ;
}
mysql_select_db( "big" , $conn );
mysql_query( "set names utf8" );
 
$price =10;
$user_id =1;
$goods_id =1;
$sku_id =11;
$number =1;
 
//生成唯一订单号
function build_order_no(){
   return date ( 'ymd' ). substr (implode(NULL, array_map ( 'ord' , str_split ( substr (uniqid(), 7, 13), 1))), 0, 8);
}
//记录日志
function insertLog( $event , $type =0){
     global $conn ;
     $sql ="insert into ih_log(event,type)
     values( '$event' , '$type' )";
     mysql_query( $sql , $conn );
}
 
//模拟下单操作
//库存是否大于0
mysql_query( "BEGIN" );   //开始事务
$sql = "select number from ih_store where goods_id='$goods_id' and sku_id='$sku_id' FOR UPDATE" ; //此时这条记录被锁住,其它事务必须等待此次事务提交后才能执行
$rs =mysql_query( $sql , $conn );
$row =mysql_fetch_assoc( $rs );
if ( $row [ 'number' ]>0){
     //生成订单
     $order_sn =build_order_no();
     $sql ="insert into ih_order(order_sn,user_id,goods_id,sku_id,price)
     values( '$order_sn' , '$user_id' , '$goods_id' , '$sku_id' , '$price' )";
     $order_rs =mysql_query( $sql , $conn );
     
     //库存减少
     $sql = "update ih_store set number=number-{$number} where sku_id='$sku_id'" ;
     $store_rs =mysql_query( $sql , $conn );
     if (mysql_affected_rows()){
         insertLog( '库存减少成功' );
         mysql_query( "COMMIT" ); //事务提交即解锁
     } else {
         insertLog( '库存减少失败' );
     }
} else {
     insertLog( '库存不够' );
     mysql_query( "ROLLBACK" );
}
?>
 
第三种,使用非阻塞的文件排他锁
 

<?php
$conn=mysql_connect("localhost","root","123456");
if(!$conn){
    echo "connect failed";
    exit;
}
mysql_select_db("big-bak",$conn);
mysql_query("set names utf8");
 
$price=10;
$user_id=1;
$goods_id=1;
$sku_id=11;
$number=1;
 
//生成唯一订单号
function build_order_no(){
  return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
}
//记录日志
function insertLog($event,$type=0){
    global $conn;
    $sql="insert into ih_log(event,type)
    values('$event','$type')";
    mysql_query($sql,$conn);
}
 
$fp = fopen("lock.txt", "w+");
if(!flock($fp,LOCK_EX | LOCK_NB)){
    echo "系统繁忙,请稍后再试";
    return;
}
//下单
$sql="select number from ih_store where goods_id='$goods_id' and sku_id='$sku_id'";
$rs=mysql_query($sql,$conn);
$row=mysql_fetch_assoc($rs);
if($row['number']>0){//库存是否大于0
    //模拟下单操作
    $order_sn=build_order_no();
    $sql="insert into ih_order(order_sn,user_id,goods_id,sku_id,price)
    values('$order_sn','$user_id','$goods_id','$sku_id','$price')";
    $order_rs=mysql_query($sql,$conn);
     
    //库存减少
    $sql="update ih_store set number=number-{$number} where sku_id='$sku_id'";
    $store_rs=mysql_query($sql,$conn);
    if(mysql_affected_rows()){
        insertLog('库存减少成功');
        flock($fp,LOCK_UN);//释放锁
    }else{
        insertLog('库存减少失败');
    }
}else{
    insertLog('库存不够');
}
fclose($fp);

 

第四种,使用redis队列

 

<?php
$store =1000;
$redis = new Redis();
$result = $redis ->connect( '127.0.0.1' ,6379);
$res = $redis ->llen( 'goods_store' );
echo $res ;
$count = $store - $res ;
for ( $i =0; $i < $count ; $i ++){
     $redis ->lpush( 'goods_store' ,1);
}
echo $redis ->llen( 'goods_store' );
?>
原博文:https://www.cnblogs.com/hangxing1996/p/6783027.html

转载于:https://www.cnblogs.com/cuculus/articles/9909229.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值