zoukankan      html  css  js  c++  java
  • 简单用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事务在高并发下性能下降很厉害,文件锁的方式也是) 有不足的地方望指正

    欢迎关注

  • 相关阅读:
    HttpClient学习整理
    编写更少量的代码:使用apache commons工具类库
    Java多线程:Callable,Future,FutureTask
    多线程下HashMap的死循环问题
    选择排序算法---直接选择排序和堆排序
    Java多线程:ThreadLocal
    插入排序算法---插入排序与希尔排序
    数据库MySQL与Oracle的一些去O注意项
    交换排序算法---冒泡排序与快速排序
    ImageMagick常用指令详解
  • 原文地址:https://www.cnblogs.com/LXJ416/p/9097923.html
Copyright © 2011-2022 走看看