啥都不说了,看代码

前台:

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

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. What's New In DevTools (Chrome 59)来看看最新Chrome 59的开发者工具又有哪些新功能

    原文:https://developers.google.com/web/updates/2017/04/devtools-release-notes#command-menu 参考:https:// ...

  2. C#之Hello World(入门 )

    C#是一种简单.现代.面向对象和类型安全的编程语言. C#由C和C++发展而来.C#(英文发音C sharp)牢固地植根于C和C++语言族谱中,是Microsoft专门为使用.NET平台而创建的. • ...

  3. iTOP-4412 开发板的 GPIO 是怎么操作的?

    Exynos4412 全部的 GPIO 都有固定的地址,为了方便操作这些 GPIO.Linux 内核 在 gpio-exynos4.h 里面定义了一些 GPIO 的宏.比如: #define EXYN ...

  4. javascript通过url向jsp页面传递中文参数乱码解决方法

    解决方法:在传递参数前将中文参数进行两次编码,jsp页面获取参数后对中文参数进行一次解码,中文参数就不会变为乱码了! 参考例子: <%@ page language="java&quo ...

  5. Idea 代码编辑错误不飘红提示

    Power Save Mode 勾选去掉即可

  6. [Functional Programming] Combine Multiple State ADT Instances with the Same Input (converge(liftA2(constant)))

    When combining multiple State ADT instances that depend on the same input, using chain can become qu ...

  7. 支付宝支付系统繁忙,请稍后再试(ALI64)错误解决

    解决方法:将商户支付參数的seller邮箱换成与partner同样的数字串,依然无法支付请检查所给參数

  8. mui 跨域请求

    <ul class="mui-table-view" style="margin-top: 25px;"> <li class="m ...

  9. ViewPager中Fragment无法显示的问题

    问题描述: Actvitiy->Fragment1 ->Fragment2 Fragment1中有1个ViewPager,ViewPager里面有包括了2个Fragment. 当第一次执行 ...

  10. poj 3592 Instantaneous Transference 【SCC +缩点 + SPFA】

    Instantaneous Transference Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 6204   Accep ...