码迷,mamicode.com
首页 > 其他好文 > 详细

简单用REDIS实现抢购逻辑

时间:2018-05-27 23:39:39      阅读:247      评论:0      收藏:0      [点我收藏+]

标签:商品   技术分享   arc   epo   tor   type   password   getc   foreign   

  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事务在高并发下性能下降很厉害,文件锁的方式也是) 有不足的地方望指正

 

欢迎关注

技术分享图片

简单用REDIS实现抢购逻辑

标签:商品   技术分享   arc   epo   tor   type   password   getc   foreign   

原文地址:https://www.cnblogs.com/LXJ416/p/9097923.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!