thinkphp5使用redis实现秒杀商品活动
如题,废话少说贴码为上↓
// 初始化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实现秒杀商品活动的更多相关文章
- .NetCore+Jexus代理+Redis模拟秒杀商品活动
开篇叙 本篇将和大家分享一下秒杀商品活动架构,采用的架构方案正如标题名称.NetCore+Jexus代理+Redis,由于精力有限所以这里只设计到商品添加,抢购,订单查询,处理队列抢购订单的功能:有不 ...
- thinkphp5.0 - Redis 实现秒杀
首先,因为秒杀这个环节在商城项目中比较常见,最近写商城项目,碰到这个功能模块,于是就拿出来给大家分享一波. 难点:高并发的情况下,正常逻辑写的话数据库的库存会出现负数,对付这类问题有很多解决方案,我就 ...
- redis实现秒杀demo
代码 package com.prosay.redis; import java.util.List; import redis.clients.jedis.Jedis; import redis.c ...
- IDEA SpringBoot+JPA+MySql+Redis+RabbitMQ 秒杀系统
先放上github地址:spike-system,可以直接下载完整项目运行测试 SpringBoot+JPA+MySql+Redis+RabbitMQ 秒杀系统 技术栈:SpringBoot, MyS ...
- PHP 使用redis实现秒杀
PHP 使用redis实现秒杀 使用redis队列,因为pop操作是原子的,即使有很多用户同时到达,也是依次执行,推荐使用(mysql事务在高并发下性能下降很厉害,文件锁的方式也是) 先将商品库存如队 ...
- thinkphp5使用redis
1.设置应用配置文件config.php type可以是很多分类File.Redis等等 2.thinkphp5使用redis新建application/index/controller/index. ...
- 39、生鲜电商平台-redis缓存在商品中的设计与架构
说明:Java开源生鲜电商平台-redis缓存在商品中的设计与架构. 1. 各种计数,商品维度计数和用户维度计数 说起电商,肯定离不开商品,而附带商品有各种计数(喜欢数,评论数,鉴定数,浏览数,etc ...
- 扩展thinkphp5的redis类方法
笔者在开发时发现,thinkphp5的自带redis类方法,只有简单的读取缓存.写入缓存的基本方法,远不能满足我们业务的需求.redis本身支持五种数据类型,string(字符串).hash(哈希). ...
- Java生鲜电商平台-redis缓存在商品中的设计与架构
Java生鲜电商平台-redis缓存在商品中的设计与架构 说明:Java开源生鲜电商平台-redis缓存在商品中的设计与架构. 1. 各种计数,商品维度计数和用户维度计数 说起电商,肯定离不开商品,而 ...
随机推荐
- 使用jQuery制作一个简易的购物车结算流程
因为今天下午时候在网上买了东西,在结算界面的时候突发奇想的也想自己动手做一个结算界面,当然了,只是一个最简易的结算界面,有商品数量的加减,有单价和小计,单个多个删除,全选和区县全选等等一些小功能,我在 ...
- Selenide UI 自动化测试
我没有拼写错误,确实不是 Selenium ,但是,只要是 Web UI 自动化测试框架,基本上都是基于Selenium 的.Selenide 也不例外.那为啥不直接用Selenium呢? 因为 ...
- js中的call()方法与apply()方法
摘自:http://blog.csdn.net/chelen_jak/article/details/21021101 在web前端开发过程中,我们经常需要改变this指向,通常我们想到的就是用cal ...
- 关于理解python类的小题
今天看了python部落翻译的一篇<一道python类的小题>文章,感觉挺有启发性,记录下来: print('A') class Person(object): print('B') de ...
- JVM 运行时的内存分配
首先我们必须要知道的是 Java 是跨平台的.而它之所以跨平台就是因为 JVM 不是跨平台的.JVM 建立了 Java 程序和操作系统之间的桥梁,JVM 是用 C 语言编写,而 C 语言不具备跨平台的 ...
- 为什么说Python 是大数据全栈式开发语言
欢迎大家访问我的个人网站<刘江的博客和教程>:www.liujiangblog.com 主要分享Python 及Django教程以及相关的博客 交流QQ群:453131687 原文链接 h ...
- JAVA模板方法
package project01; abstract class MyRuntime{ public final void runtime(){ long starttime =System.cur ...
- JavaScript获取数组最小值和最大值的方法
本文实例讲述了JavaScript获取数组最小值和最大值的方法.分享给大家供大家参考.具体如下: ? 1 2 3 4 5 6 var arr = new Array(); arr[0] = 100; ...
- asp.net core webapi 服务端配置跨域
在前后端分离开发中服务端仅仅只为前端提供api接口,并且前后端往往单独部署,此时就会出现浏览器跨域问题.asp.net core提供了简单优雅的解决方案. 在startup文件的Configure添加 ...
- ldap命令的使用
转自:http://blog.chinaunix.net/uid-20690190-id-4085176.html 增:ldapadd 1)选项: -x 进行简单认证 -D 用来绑定服务器的D ...