zoukankan      html  css  js  c++  java
  • php+redis秒杀

    啥都不说了,看代码

    前台:

    包括开始和结束的秒杀时间,倒计时插件,统一看一遍再去写代码,思路会更清晰。

     js文件引入一个.min.js和一个插件js(在下面,自己复制吧)

    // JavaScript Document
    $(function(){
        
        //计算内容上下padding
        reContPadding({main:"#main",header:"#header",footer:"#footer"});
        function reContPadding(o){
            var main = o.main || "#main",
                header = o.header || null,
                footer = o.footer || null;
            var cont_pt = $(header).outerHeight(true),
                cont_pb = $(footer).outerHeight(true);
            $(main).css({paddingTop:cont_pt,paddingBottom:cont_pb});
        }
    });

    html代码:

    <span id="t_d">00天</span>
    <span id="t_h">00时</span>
    <span id="t_m">00分</span>
    <span id="t_s">00秒</span>
    
    <input type="hidden" id="start" value="<?php date_default_timezone_set('PRC');echo  strtotime(date('Y-m-d H:i:s'))-strtotime($goods['start_time']);?>">
    <input type="hidden" id="end" value="<?php date_default_timezone_set('PRC');echo strtotime(date('Y-m-d H:i:s'))-strtotime($goods['end_time'])?>" >
    
    
    <script type="text/javascript">
       //判断时间
            var start = document.getElementById("start").value;
            var end = document.getElementById("end").value;
          if(start>=0 && end<0)
          {
             timer(end*-1);
          }
    
        function timer(intDiff) {
            window.setInterval(function () {
                var day = 0,
                    hour = 0,
                    minute = 0,
                    second = 0; //时间默认值
                if (intDiff > 0) {
                    day = Math.floor(intDiff / (60 * 60 * 24));
                    hour = Math.floor(intDiff / (60 * 60)) - (day * 24);
                    minute = Math.floor(intDiff / 60) - (day * 24 * 60) - (hour * 60);
                    second = Math.floor(intDiff) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60);
                }
                if (minute <= 9) minute = '0' + minute;
                if (second <= 9) second = '0' + second;
                $('#t_d').html(day + "");
                $('#t_h').html('<s id="h"></s>' + hour + '');
                $('#t_m').html('<s></s>' + minute + '');
                $('#t_s').html('<s></s>' + second + '');
                intDiff--;
            }, 1000);
        }
    
    
    
        function GetRTime(end){
    
            var EndTime= new Date(end);
            var NowTime = new Date();
            var t =EndTime.getTime() - NowTime.getTime();
            var d=0;
            var h=0;
            var m=0;
            var s=0;
            if(t>=0){
                d=Math.floor(t/1000/60/60/24);
                h=Math.floor(t/1000/60/60%24);
                m=Math.floor(t/1000/60%60);
                s=Math.floor(t/1000%60);
            }
    
    
            document.getElementById("t_d").innerHTML = d + "";
            document.getElementById("t_h").innerHTML = h + "";
            document.getElementById("t_m").innerHTML = m + "";        document.getElementById("t_s").innerHTML = s + "";    }   $(function () {        $(".ms").click(function () {            var id = $(this).attr("ids");            $.ajax({                type: "get",                url: "?r=ms/buyms",                data: {id:id},            dataType:"json",                success: function(msg){                    alert(msg['message'])                }            });        })    })</script>
    
     

    后台:

    展示商品时,首先应该想到静态页面去优化服务器(我是根据详情页用id查询并赋值):

     /**
         * @param $gid
         * 生成静态页面
         *
         */
        public function actionOb($gid)
        {
            $goods_statis_file = "../views/pages/goods/ms_".md5($gid).".html";//对应静态页文件
            if(file_exists($goods_statis_file)){
                ob_start();
                flush();
                echo file_get_contents($goods_statis_file);//输出静态文件内容
                exit;
            }else{
                ob_start();
    
                //从数据库读取数据,并赋值给相关变量
                $goods = yii::$app->db->createCommand("select * from gobuy as go inner join goods as g on go.buy_goods_id=g.goods_id where g.goods_id='$gid'")->queryOne();
                include ("../views/goods/product_ms.html");//加载对应的商品详情页模板
                $content = ob_get_contents();//把详情页内容赋值给$content变量
                file_put_contents($goods_statis_file,$content);//写入内容到对应静态文件中
                ob_end_flush();//输出商品详情页信息
            }
    
        }

    秒杀的方法:

    
    
    <?php
    namespace frontendcontrollers;
    
    use Yii;
    use yiiwebController;
    
    /**
     * Site controller
     */
    class MsController extends Controller
    {
        public $layout = false;
    
        /**
         * 商品只能购买一件商品   商品ID、当前用户ID、商品数量,存入redis,
         * 通知当前用户,秒杀成功,或失败
         * 并将redis的商品库存队列 递减
         *
         */
        public function actionBuyms(){
    //设置当前时间是中国时区
            date_default_timezone_set('PRC');
    //      接受商品ID  ajax传来的id
    //      $goods_id = yii::$app->request->get('goods_id');
            $goods_id=1;
    //      当前登录用户ID
            $user_id = 1;
    //      当前时间
            $date = date('Y-m-d H:i:s');
    //      首先判断开始时间是否到
    //      在队列查询开始时间
            $start_time = Yii::$app->redis->get('start_time'.$goods_id);
            if(empty($start_time)||$start_time>$date){
                echo json_encode(array('code'=>1002,'message'=>'秒杀时间还未开始'));exit;
            }
    //      判断结束时间是否到
            $end_time  = Yii::$app->redis->get('end_time'.$goods_id);
            if(empty($end_time)||$date>=$end_time){
                echo json_encode(array('code'=>1002,'message'=>'秒杀已经结束了'));exit;
            }
            //取出储存在redis里的库存
           $num = Yii::$app->redis->get('num'.$goods_id);
            if($num<=0){
                echo json_encode(array('code'=>1001,'message'=>'已被抢空了...请等待下次抢购'));exit;
            }else{           
           $msg = json_encode(['user_id'=>1,'goods_id'=>1,'buy_num'=>$goods_id]);            
        //更新库存  decr递减            
        $u=Yii::$app->redis->decr('num'.$goods_id);            
        if($u) {               
         //储存用户信息到用户的队列   秒杀人员的总队列                
          Yii::$app->redis->lpush('yes_buy',$msg);               
            echo json_encode(array('code'=>1000,'message'=>'抢购成功,稍后为您出单,预计时间3分钟'));            
    }       
    }    
    }    
    /**     * @return string     *     * 生成订单为定时任务     在服务器每两分钟执行一次,等待1分钟     */    
    /**     * 设置初始值,理论上,应为后台管理员手动设定秒杀商品     *     *     * 模拟给予   开始时间、结束时间、库存在redis储存的值     */    
    public function actionSetbuyuser(){        
    //默认开始时间为    2017-03-28 00:00:00        
    $start_time = '2017-03-28 00:00:00';       
    //默认结束时间为    2017-03-28 00:00:00       
    $end_time = '2017-03-28 24:00:00';       
    //默认库存为1        $num = 10;        
    //商品id   为了区分商品信息、库存   不会打乱各个商品信息        
    $goods_id = 1;        //设置库存        
    Yii::$app->redis->set('num'.$goods_id,$num);        
    //设置当前商品的开始时间        
    Yii::$app->redis->set('start_time'.$goods_id,$start_time);       
    //设置当前商品的结束时间        
    Yii::$app->redis->set('end_time'.$goods_id,$end_time);    
    }
    }
    
    
    
    
    

    yii2有个console定时任务:

    Windows下命令行执行这个文件,linux用crontab定时任务执行也可以直接yii执行

    下面代码意思是,将队列的信息一个个推出销毁,并入库生成订单返回给用户

    
    
    <?php
    /**
     * @link http://www.yiiframework.com/
     * @copyright Copyright (c) 2008 Yii Software LLC
     * @license http://www.yiiframework.com/license/
     */
    
    namespace consolecontrollers;
    use yii;
    use yiiconsoleController;
    
    /**
     * This command echoes the first argument that you have entered.
     *
     * This command is provided as an example for you to learn how to create console commands.
     *
     * @author Qiang Xue <qiang.xue@gmail.com>
     * @since 2.0
     */
    class TestController extends Controller
    {
        /**
         * This command echoes what you have entered as the message.
         * @param string $message the message to be echoed.
         */
    
        public function actionIndex()
        {
            while (true){
             //获取队列最右用户信息
                $inf=yii::$app->redis->brpop('yes_buy',30);
    
                if(empty($inf))
                {
                    break;
                }
                $info=json_decode($inf[1],true);
                //将商品信息查询出来
                $goods = yii::$app->db->createCommand("select * from goods where goods_id=1")->queryOne();
            //生成订单
                //获取唯一订单号
                $date = date('Y-m-d H:i:s');
                $sn=date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
    
    
                $inser="insert into `order`(`order_sn`,`order_price`,`order_user`,`order_time`,`goods_num`,`goods_id`)values('".$sn."','".$goods['goods_price']*$info['buy_num']."','".$info['user_id']."','".$date."','".$info['buy_num']."','".$info['goods_id']."')";
    
                $or = yii::$app->db->createCommand($inser)->execute();           
           if($or)
            {
           //库存减少 订单生成一个,库存减少一个
            $sql="update gobuy set buy_num=buy_num-1 where buy_goods_id=".$info['goods_id'];
             $or = yii::$app->db->createCommand($sql)->execute();
              }
              }
            }
        }
  • 相关阅读:
    java连接oracle数据库的实现代码
    java.sql.SQLException: Io 异常: Connection refused(DESCRIPTION=(TMP=)(VSNNUM=186646784)(ERR=12505)(ERR
    Java连接MySQl数据库实现代码
    在JSP中使用BootStrap
    在Eclipse中添加添加一些有助于开发的插件
    再eclipse的javaweb项目中添加JQuery文件时jquery-2.1.4.min.js报错
    Oracle中的触发器
    oracle----约束
    oracle----删除数据
    oracle----修改表中的数据
  • 原文地址:https://www.cnblogs.com/dwj97/p/6675530.html
Copyright © 2011-2022 走看看