如题,废话少说贴码为上↓

// 初始化redis数据列表 模拟库存50,redis搭建在centos中已开启
public function redisinit(){ $store=50; // 库存50
$redis=$this->redis(); //接入redis
$redis->del('goods_store'); // 删除库存列表
$res=$redis->llen('goods_store'); //返回库存长度,这里已经是0
$count=$store-$res;
for($i=0;$i<$count;$i++){
$redis->lpush('goods_store',1); //列表推进50个,模拟50个商品库存
} }
// 秒杀入口
public function kills(){
$id = input("id"); //商品编号
if(!$id)
return $this->insertlog(0);//记录失败日志
$redis = $this->redis(); // 接入redis
$count=$redis->lpop('goods_store'); //减少库存,返回剩余库存数
if(!$count){ //库存为0
$this->insertlog(0); //记录秒杀失败的 日志
return false;
}else{// 有库存
$ordersn = $this->build_order_no(); //订单号随机生成
$uid = rand(0,9999); //用户id随机生成,正式项目可以启用登录的session
$status = 1; // 订单状态
$data = Db::name("ab_goods")->field("count,amount")->where("id",$id)->find();//查找商品
if(!$data)
return $this->insertlog(0); //商品不存在
$result = Db::name("ab_order")->insert(["order_sn"=>$ordersn,"user_id"=>$uid,"goods_id"=>$id,"price"=>$data['amount'],"status"=>$status,'addtime'=>date('Y-m-d H:i:s')]); //订单入库
$res = Db::name("ab_goods")->where("id",$id)->setDec("count"); //库存减少
if($res)
$this->insertlog(); //记录成功的日志
else
$this->insertlog(0);//记录失败的日志 }
} //生成唯一订单
function build_order_no(){
return date('ymd').substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
} // 记录日志 状态1成功 0失败
function insertlog($status=1){
return Db::name("ab_log")->insertGetId(["count"=>1,"status"=>$status,"addtime"=>date('Y-m-d H:i:s')]);
}

使用apache压力测试工具AB抢购商品

AB压力测试,模拟多用户秒杀商品
-r 指定接收到错误信息时不退出程序
-t 等待响应的最大时间
-n 指定压力测试总共的执行次数
-c 用于指定压力测试的并发数
例:秒杀商品,60秒内发起3000个请求,并发600次,接口地址 http://192.168.0.20:86/api/kill/kills/id/1
D:\wamp64\bin\apache\apache2.4.23\bin>ab -r -t 60 -n 3000 -c 600 http://192.168.0.20:86/api/kill/kills/id/1
正常的逻辑写法秒杀开始时候库存会出现负数

命令行:D:\wamp64\bin\apache\apache2.4.23\bin>ab -r -t 60 -n 1000 -c 100 http://192.168.0.20:86/api/kill/kills/id/1
60秒内发起1000个请求,并发100次,秒杀50个库存的商品,库存出现负数(-53),订单有103个!不测不知道,一测吓一跳~ 正常来说50个库存只会生成50个订单,在高并发下测试就懵逼了!

  

用法:

1.先跑一波库存接口(初始化50个库存):http://192.168.0.20:86/api/kill/redisinit

2 命令行:D:\wamp64\bin\apache\apache2.4.23\bin>ab -r -t 60 -n 1000 -c 100 http://192.168.0.20:86/api/kill/kills/id/1

3.如果ab测试中出现错误,该计算机关闭连接 Test aborted after 10 failures  apr_socket_con等错误请优化apache服务器,或者如下操作

、停止Apache服务;
、找到apache/conf/httpd.conf文件,用文本编辑器打开找到这两行:
# Server-pool management (MPM specific)
# Include conf/extra/httpd-mpm.conf
把第二行include........这行的注释去掉。 、找到apache/conf/extra/httpd-mpm.conf文件,打开,找到: <IfModule mpm_winnt_module>
ThreadsPerChild
MaxRequestsPerChild
</IfModule> 把上面的150调大,Windows下最大为1920.
注意:尖括号里的名字是winnt,不要看错了

centos6.5安装redis指南 http://www.cnblogs.com/leisir/p/8250840.html

如图

运行问cmd命令后再来看看数据库

ab_goods 库存数量count此时已经是0

ab_order 订单表已经有了50个订单

ab_log 日志表中有1000条记录,其中50条成功的,950条抢购失败的记录

表3张 商品 订单 日志 ab_goods ab_order ab_log

CREATE TABLE `ab_goods` (
`id` int() unsigned NOT NULL AUTO_INCREMENT,
`count` int() NOT NULL DEFAULT '',
`status` tinyint() DEFAULT NULL,
`title` varchar() DEFAULT NULL,
`amount` decimal(,) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8; CREATE TABLE `ab_log` (
`id` int() unsigned NOT NULL AUTO_INCREMENT,
`addtime` datetime DEFAULT NULL,
`status` tinyint() DEFAULT NULL,
`count` int() unsigned DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8; CREATE TABLE `ab_order` (
`id` int() unsigned NOT NULL AUTO_INCREMENT,
`order_sn` varchar() NOT NULL,
`user_id` int() NOT NULL,
`goods_id` int() NOT NULL,
`price` decimal(,) NOT NULL,
`status` tinyint() DEFAULT '',
`addtime` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT= DEFAULT CHARSET=utf8;

thinkphp5使用redis实现秒杀商品活动的更多相关文章

  1. .NetCore+Jexus代理+Redis模拟秒杀商品活动

    开篇叙 本篇将和大家分享一下秒杀商品活动架构,采用的架构方案正如标题名称.NetCore+Jexus代理+Redis,由于精力有限所以这里只设计到商品添加,抢购,订单查询,处理队列抢购订单的功能:有不 ...

  2. thinkphp5.0 - Redis 实现秒杀

    首先,因为秒杀这个环节在商城项目中比较常见,最近写商城项目,碰到这个功能模块,于是就拿出来给大家分享一波. 难点:高并发的情况下,正常逻辑写的话数据库的库存会出现负数,对付这类问题有很多解决方案,我就 ...

  3. redis实现秒杀demo

    代码 package com.prosay.redis; import java.util.List; import redis.clients.jedis.Jedis; import redis.c ...

  4. IDEA SpringBoot+JPA+MySql+Redis+RabbitMQ 秒杀系统

    先放上github地址:spike-system,可以直接下载完整项目运行测试 SpringBoot+JPA+MySql+Redis+RabbitMQ 秒杀系统 技术栈:SpringBoot, MyS ...

  5. PHP 使用redis实现秒杀

    PHP 使用redis实现秒杀 使用redis队列,因为pop操作是原子的,即使有很多用户同时到达,也是依次执行,推荐使用(mysql事务在高并发下性能下降很厉害,文件锁的方式也是) 先将商品库存如队 ...

  6. thinkphp5使用redis

    1.设置应用配置文件config.php type可以是很多分类File.Redis等等 2.thinkphp5使用redis新建application/index/controller/index. ...

  7. 39、生鲜电商平台-redis缓存在商品中的设计与架构

    说明:Java开源生鲜电商平台-redis缓存在商品中的设计与架构. 1. 各种计数,商品维度计数和用户维度计数 说起电商,肯定离不开商品,而附带商品有各种计数(喜欢数,评论数,鉴定数,浏览数,etc ...

  8. 扩展thinkphp5的redis类方法

    笔者在开发时发现,thinkphp5的自带redis类方法,只有简单的读取缓存.写入缓存的基本方法,远不能满足我们业务的需求.redis本身支持五种数据类型,string(字符串).hash(哈希). ...

  9. Java生鲜电商平台-redis缓存在商品中的设计与架构

    Java生鲜电商平台-redis缓存在商品中的设计与架构 说明:Java开源生鲜电商平台-redis缓存在商品中的设计与架构. 1. 各种计数,商品维度计数和用户维度计数 说起电商,肯定离不开商品,而 ...

随机推荐

  1. RSA加解密实现

    RSA是由MIT的三位数学家R.L.Rivest,A.Shamir和L.Adleman[Rivest等1978, 1979]提出的一种用数论构造双钥的方法,被称为MIT体制,后来被广泛称之为RSA体制 ...

  2. Linux 文本编辑器vi命令

    1.Vim Vim  是一个功能强大的全屏幕文本编辑器,是 Linux/UNIX 上最常用的文本编辑器,它的作用是建立.编辑.显示文本文件. Vim 没有菜单,只有命令 2.Vim 工作模式 3.插入 ...

  3. win10 音频服务未响应的解决方法

    最近在调试usb audio设备,由于使用的是自己的audio 设备,所以要频繁的更换采样率,可是 在win10中经常出现一些莫名其妙的问题,今天这个问题就是折腾了我好久才搞定的. 当把usb aud ...

  4. Flask快速入门,知识整理

    一.Flask介绍(轻量级的框架,非常快速的就能把程序搭建起来) Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是 ...

  5. Angular5系列教程:ng-book2-angular-5-r66 土家翻译,话糙理不糙

    嗯, 在工作还辣么忙之时,看了这本书,感觉很不错.想分享给国内朋友们.结合自己的理解和整理加翻译,可能有点糙,但是,话糙理不糙嘛.出系列,不知道会不会弃坑,不立Flag了.持续更新.....我会放在印 ...

  6. 转:JAVA常见错误处理方法 和 JVM内存结构

    OutOfMemoryError在开发过程中是司空见惯的,遇到这个错误,新手程序员都知道从两个方面入手来解决:一是排查程序是否有BUG导致内存泄漏:二是调整JVM启动参数增大内存.OutOfMemor ...

  7. 通过渲染改变tabBarItem的背景图片

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #703daa } p.p2 { margin: 0.0px 0. ...

  8. Hadoop源码篇---解读Mapprer源码Input输入

    一.前述 上次分析了客户端源码,这次分析mapper源码让大家对hadoop框架有更清晰的认识 二.代码 自定义代码如下: public class MyMapper extends Mapper&l ...

  9. Java学习笔记10---访问权限修饰符如何控制成员变量、成员方法及类的访问范围

    1.Java有三种访问权限修饰符,分别为public.protected.private,还有一种为缺省权限修饰符的情况,记为default.其中,可以由public和default来修饰类:这四种修 ...

  10. docker:(4)利用WebHook实现持续集成

    研发小伙伴可能对下列操作步骤会深有体会 写代码-->提交代码-->打包-->发布 在项目调试测试阶段,可能经常需要重复上面的步骤,以便将最新代码部署到特定环境供测试人员或其他人员使用 ...