简单用REDIS实现抢购逻辑

  1. 创建数据表

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------

-- Table structure for ih_goods

-- ----------------------------

DROP TABLE IF EXISTS `ih_goods`;

CREATE TABLE `ih_goods` (

  `goods_id` int(10) unsigned NOT NULL AUTO_INCREMENT,

  `cat_id` int(11) NOT NULL,

  `goods_name` varchar(255) NOT NULL,

  PRIMARY KEY (`goods_id`)

) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

-- ----------------------------

-- Records of ih_goods

-- ----------------------------

INSERT INTO `ih_goods` VALUES ('1', '0', '小米手机');

-- ----------------------------

-- Table structure for ih_log

-- ----------------------------

DROP TABLE IF EXISTS `ih_log`;

CREATE TABLE `ih_log` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `event` varchar(255) NOT NULL,

  `type` tinyint(4) NOT NULL DEFAULT '0',

  `addtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

  PRIMARY KEY (`id`)

) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- ----------------------------

-- Records of ih_log

-- ----------------------------

-- ----------------------------

-- Table structure for ih_order

-- ----------------------------

DROP TABLE IF EXISTS `ih_order`;

CREATE TABLE `ih_order` (

  `id` int(11) NOT NULL AUTO_INCREMENT,

  `order_sn` char(32) NOT NULL,

  `user_id` int(11) NOT NULL,

  `status` int(11) NOT NULL DEFAULT '0',

  `goods_id` int(11) NOT NULL DEFAULT '0',

  `sku_id` int(11) NOT NULL DEFAULT '0',

  `price` float NOT NULL,

  `addtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=3697 DEFAULT CHARSET=utf8 COMMENT='订单表';

-- ----------------------------

-- Records of ih_order

-- ----------------------------

-- ----------------------------

-- Table structure for ih_store

-- ----------------------------

DROP TABLE IF EXISTS `ih_store`;

CREATE TABLE `ih_store` (

  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,

  `goods_id` int(11) NOT NULL,

  `sku_id` int(10) NOT NULL DEFAULT '0',

  `number` int(11) unsigned NOT NULL DEFAULT '0',

  `freez` int(11) NOT NULL DEFAULT '0' COMMENT '虚拟库存',

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='库存';

  1. 先将商品库存如队列

    <?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');  
    ?> 

  1. 抢购、描述逻辑

<?php

     /**

  *   数据库封装

  */

    class PDORepository{

        const USERNAME="root";

        const PASSWORD="@liu416115";

        const HOST="47.93.33.115";

        const DB="my";

        private function getConnection(){

            $username = self::USERNAME;

            $password = self::PASSWORD;

            $host = self::HOST;

            $db = self::DB;

            $connection = new PDO("mysql:dbname=$db;host=$host",$username,$password);

            return $connection;

        }

        public function queryList($sql, $args){

            $connection = $this->getConnection();

            $stmt = $connection->prepare($sql);

            $stmt->execute($args);

            return $stmt;

        }

    }

/**

 * 封装的REDIS  可以自己修改

 */

class RedisClass

{

public $resuorce ;

public function __construct()

{

$this->resuorce=new Redis();

}

public function connect()

{

$this->resuorce->connect('47.93.33.115',6379);

}

public  function lpush($key,$value)

{

return $this->resuorce->lpush($key,$value);

}

public function rbpop($key)

{

return $this->resuorce->rpop($key);

}

public function lpop($key)

{

return $this->resuorce->lpop($key);

}

public function  llen($key){

  return  $this->resuorce->llen($key);

}

public function rpoplpush($reurce_key,$dest_key)

{

return $this->resuorce->rpoplpush($reurce_key,$dest_key);

}

public function delete($keys)

{

return $this->resuorce->del($keys);

}

}

  

    $redis = new RedisClass();

    $redis->connect('47.93.33.115',6379);

    $count=$redis->lpop('goods_store');

    if(!$count){

       insertLog(' 以抢光');

       return;

    }

$user_name = time();

$result = $redis->lpush('user_store',$user_name);

if(!$result) {

  insertLog(' 抢购失败');

       return;

} else {

echo "抢购成功";

}

$price=10;

$goods_id=1;

$sku_id=11;

$number=1;

// 抢购成功保存到数据库

$user_id = $redis->rbpop('user_store');

$redis->lpush('used_user_store',$user_id);

$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') ";

$rep = new PDORepository();

$rep->queryList($sql,array());

$sql="update ih_store set number=number-($number) where sku_id='$sku_id'";

$result = $rep->queryList($sql,array());

if($result){

    insertLog('inc');

}else {

    insertLog('dec');

}

function build_order_no(){

 return date('ymd').rand()*100;

}

function insertLog($event,$type=0){

 $sql="insert into ih_log(:event,:type) values('$event','$type')";

  $rep = new PDORepository();

  $rep->queryList($sql,array(':event'=>$event,':type'=>$type));

}

模拟5000高并发测试

//ab -r -n 6000 -c 5000  http://47.93.33.115/qiang.php

总结:使用redis队列,因为pop操作是原子的,即使有很多用户同时到达,也是依次执行,推荐使用(mysql事务在高并发下性能下降很厉害,文件锁的方式也是) 有不足的地方望指正

欢迎关注

猜你喜欢

转载自www.cnblogs.com/LXJ416/p/9097923.html
今日推荐