啥都不说了,看代码

前台:

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

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. projecteuler----&gt;problem=11----Largest product in a grid

    In the 2020 grid below, four numbers along a diagonal line have been marked in red. 08 02 22 97 38 1 ...

  2. 第十五章 MySQL 数据库

    学习要点:1.Web 数据库概述2.MySQL 的操作3.MySQL 常用函数4.SQL 语句详解5.phpMyadmin 一.Web数据库概述 现在,我们已经熟悉了PHP 的基础知识,这是我们想暂时 ...

  3. Split Animation Clip From FBX and Multiply Mode Sprite

    Use Script To Creat 2D Animation Clip From Multiply Mode Sprite 很多时候美工拿过来的一张序列帧图片,我们需要转换成 Multiply M ...

  4. puppeteer 相关知识

    page.waitForNavigation: 但我们通过代码执行到页面跳转时,我们需要等待跳转完成再作其他事情.使用page.waitForNavigation会等待跳转完成.(一般作用在点击链接或 ...

  5. react-native + teaset(Drawer)实现侧边菜单

    1.代码 /** * 购物车 */ import React, {Component} from 'react'; import { View, Image, } from 'react-native ...

  6. mysqli 实例

    1.封装数据库连接(connect.php): <?php // 封装数据库连接 // 设置页面编码声明 header("Content-type: text/html; charse ...

  7. freemarker相关

    大部分引入:http://www.blogjava.net/alinglau36/archive/2011/02/23/344970.html Freemarker操作字符串 1.substring( ...

  8. 灰色预测--matlab&python实现

    function SGrey X0 = input('请输入原始负荷数据:'); %输入原始数据 n = length(X0); %原始n年数据 %累加生成 X1 = zeros(1,n); for ...

  9. asp.net core mvc视频A:笔记5-1.路由规则

    方法一:通过MapRoute方法,配置文件位置 小例子:如果所有路径都要在admin下,可以这样写 方法二:通过路由属性 相对路由 现在需要加/admin/home/index才能正常访问原来的默认页 ...

  10. fstream之seekp/seekg/ios::ate/ios::app

    在程序开发中,IO处理无处不在,经常会在代码中遇到特殊的IO处理需求 1.描述 需求:如果文件不存在则创建,存在则打开,然后先读取文件的末行,然后在文件末尾写入. 代码: #include <i ...