啥都不说了,看代码

前台:

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

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>= && end<)
{
timer(end*-);
} function timer(intDiff) {
window.setInterval(function () {
var day = ,
hour = ,
minute = ,
second = ; //时间默认值
if (intDiff > ) {
day = Math.floor(intDiff / ( * * ));
hour = Math.floor(intDiff / ( * )) - (day * );
minute = Math.floor(intDiff / ) - (day * * ) - (hour * );
second = Math.floor(intDiff) - (day * * * ) - (hour * * ) - (minute * );
}
if (minute <= ) minute = '' + minute;
if (second <= ) second = '' + 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--;
}, );
} function GetRTime(end){ var EndTime= new Date(end);
var NowTime = new Date();
var t =EndTime.getTime() - NowTime.getTime();
var d=;
var h=;
var m=;
var s=;
if(t>=){
d=Math.floor(t////);
h=Math.floor(t///%);
m=Math.floor(t//%);
s=Math.floor(t/%);
} 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 frontend\controllers; use Yii;
use yii\web\Controller; /**
* 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=;
// 当前登录用户ID
$user_id = ;
// 当前时间
$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'=>,'message'=>'秒杀时间还未开始'));exit;
}
// 判断结束时间是否到
$end_time = Yii::$app->redis->get('end_time'.$goods_id);
if(empty($end_time)||$date>=$end_time){
echo json_encode(array('code'=>,'message'=>'秒杀已经结束了'));exit;
}
//取出储存在redis里的库存
$num = Yii::$app->redis->get('num'.$goods_id);
if($num<=){
echo json_encode(array('code'=>,'message'=>'已被抢空了...请等待下次抢购'));exit;
}else{
       $msg = json_encode(['user_id'=>,'goods_id'=>,'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'=>,'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 = ; //设置库存
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 console\controllers;
use yii;
use yii\console\Controller; /**
* 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',); if(empty($inf))
{
break;
}
$info=json_decode($inf[],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(), , ), ))), , ); $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();
          }
          }
        }
    }

php+redis秒杀的更多相关文章

  1. Redis秒杀系统架构设计-微信抢红包

    导读 前二天我写了一篇,Redis高级项目实战(点我直达),SpringBoot整合Redis附源码(点我直达),今天我们来做一下Redis秒杀系统的设计.当然啦,Redis基础知识还不过关的,先去加 ...

  2. Redis秒杀实战-微信抢红包-秒杀库存,附案例源码(Jmeter压测)

    导读 前二天我写了一篇,Redis高级项目实战(点我直达),SpringBoot整合Redis附源码(点我直达),今天我们来做一下Redis秒杀系统的设计.当然啦,Redis基础知识还不过关的,先去加 ...

  3. redis秒杀

    用Redis轻松实现秒杀系统 秒杀系统的架构设计 秒杀系统,是典型的短时大量突发访问类问题.对这类问题,有三种优化性能的思路: 写入内存而不是写入硬盘 异步处理而不是同步处理 分布式处理 用上这三招, ...

  4. php redis 秒杀demo

    $redis = new Redis(); $redis->connect("127.0.0.1", "6379"); $redis->select ...

  5. redis秒杀系统数据同步(保证不多卖)

    东西不多卖 秒杀系统需要保证东西不多卖,关键是在多个客户端对库存进行减操作时,必须加锁.Redis中的Watch刚好可以实现一点.首先我们需要获取当前库存,只有库存中的食物小于购物车的数目才能对库存进 ...

  6. 重学 Java 设计模式:实战享元模式「基于Redis秒杀,提供活动与库存信息查询场景」

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 程序员‍‍的上下文是什么? 很多时候一大部分编程开发的人员都只是关注于功能的实现,只 ...

  7. 解决redis秒杀超卖的问题

    我们再使用redis做秒杀程序的时候,解决超卖问题,是重中之重.以下是一个思路. 用上述思路去做的话,我们再用户点击秒杀的时候,只需要检测,kucun_count中是否能pop出数据,如果能pop出来 ...

  8. laravel基于redis实现的一个简单的秒杀系统

    说明:网上很多redis秒杀系统的文章,看的都是一头雾水,然后自己来实现一个,也方便以后自己学习 实现的方式是用的redis的list队列,框架为laravel 核心部分为list的pop操作,此操作 ...

  9. 对redis高并发测试的研究

    以下引用大神的: 测试项目: https://github.com/14251104246/redis-demo.git 准备 使用docker-compose命令启动redis服务器(可以用其他方式 ...

随机推荐

  1. WebLogic Server 12.2.1 多租户安装配置

    1.安装WebLogic 12.2.1版本 下载安装的时候记住选择Fusion Middleware Infrastructer Installer. 2.安装OTD OTD需要单独下载安装,安装的时 ...

  2. 转:http2基本中文翻译

    https://github.com/fex-team/http2-spec/blob/master/HTTP2%E4%B8%AD%E8%8B%B1%E5%AF%B9%E7%85%A7%E7%89%8 ...

  3. ExtentReports 结合 TestNg 生成自动化 html 报告 (支持多 suite)

    转载:https://testerhome.com/topics/8134 重要说明:报告监听器源码修复一些bug,不再此处更新代码,最新代码可以到github查看最新报告监听器源码 前几天分享了ht ...

  4. vlan 介绍

    简介      在Linux中安装了802.1Q标签VLAN功能.VLAN是虚拟分配以太网的功能. 使用VLAN ID从物理上将一个以太网分割开.在VLAN环境下,具有相同VLAN ID 就可以相互通 ...

  5. lodash round

    _.round(number, [precision=0]) 根据 precision 四舍五入 number. _.round(4.006); // => 4 _.round(4.006, 2 ...

  6. HTML ui ol dl

    <!-- 超链接target的属性 _blank 在新窗体中打开被链接文档. _self 默认. 在同样的框架中打开被链接文档. _parent 在父框架集中打开被链接文档. _top 在整个窗 ...

  7. Tabs or Spaces?

    Never mix tabs and spaces. The most popular way of indenting Python is with spaces only. The second- ...

  8. Kubernetes使用prometheus+grafana做一个简单的监控方案

    前言 本文介绍在k8s集群中使用node-exporter.prometheus.grafana对集群进行监控.其实现原理有点类似ELK.EFK组合.node-exporter组件负责收集节点上的me ...

  9. 更改 easyUI 的皮肤样式

    我的版本是:jquery-easyui-1.3.2.根据官方提供的皮肤样式,——在theme 里面: 只需要在引入的 页面中 link样式的地址改变即可: <link rel="sty ...

  10. 10、驱动中的阻塞与非阻塞IO

        阻塞,就是在获取资源的时候,不能获取到,那么就会将当前的进程挂起(睡眠,也就是将当前进程从调度器拿走了,不会调度当前进程),直到满足条件为止再进行操作.相反,非阻塞,就是即使不能获取到资源,非 ...