<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Log;
use Mockery\Exception;
use \Redis;
use App\Jobs\SeckillGoods;
class SeckillController extends Controller
{
protected $uid; // 用户id
protected $goodsId = 10086; // 秒抢商品
protected $goodsNum = 100; // 数量限制
protected $redis; // redis实例
protected $lockPrefix = 'lock:';
protected $lockExpireTime = 10;
protected $goodsCacheKeyTag = [
'goodsNumCacheKey' => 'goods_num',
'isSetGoods' => 'is_set_goods_status',
'hadGetGoodsMembers' => 'had_get_goods_members',
'limitUserNumKey' => 'limit_user_num'
];
public function __construct()
{
$redis = new Redis;
$redis->connect('127.0.0.1');
$redis->select(5);
$this->redis = $redis;
$this->uid = intval( request('uid'));
}
/**
* 加锁, 并发下的原子性操作
*/
public function limitAccessFrequency()
{
return $this->redis->set($this->lockPrefix . $this->uid , true , array('nx', 'ex' => $this->lockExpireTime));
}
/**
* 销毁锁
*/
public function __destruct()
{
$this->redis->del($this->lockPrefix . $this->uid);
}
/**
* 开始抢购
* @return array
*/
public function seckill()
{
$uid = $this->uid;
if (empty($uid)) {
return [
'status' => false,
'msg' => '参数错误'
];
}
// 加锁,限制用户访问速率
if( empty($this->limitAccessFrequency())){
return [
'status' => false,
'msg' => '请求频繁~~~~~~~~~~~'
];
}
// 进入队列抢购
return $this->interQueue($uid);
}
/**
* 进入抢购队列
* @param $uid
* @return array
*/
public function interQueue($uid)
{
$redis = $this->redis;
$goodsNumCacheKey = $this->goodsCacheKeyTag['goodsNumCacheKey'];
$hadGetGoodsMembers = $this->goodsCacheKeyTag['hadGetGoodsMembers'];
// 限制进入队列的人数
$limitStatus = $this->limitUser($uid, $this->goodsNum);
if (!$limitStatus['status']) {
return $limitStatus;
}
try {
// 开始redis事务: 抢购到的商品数量加1 ; 事务可能失败
$redis->watch($goodsNumCacheKey);
$res = $redis->multi()
->incr($goodsNumCacheKey)
->exec();
if ($res[0] <= $this->goodsNum) {
$redis->sAdd($hadGetGoodsMembers, $uid); // 抢购成功写入用户名单
} else {
return [
'status' => false,
'msg' => $uid . '来晚一步啦, 商品已经抢空3'
];
}
} catch (Exception $e) {
return [
'status' => false,
'msg' => $uid . '系统繁忙,请稍后再试'
];
}
// 异步写数据
$data = [
'goods_id' => $this->goodsId,
'uid' => $uid,
'goods_num' => 1,
'created_at' => intval(LARAVEL_START)
];
SeckillGoods::dispatch($data);
return ['status' => true, 'msg' => $uid . '抢购成功'];
}
/**
* 限制用户流
* @param $uid
* @param int $num
* @return array
*/
public function limitUser($uid, $goodsN = 100)
{
// 限定人数+50进入
$num = $goodsN + 50;
$limitUserNumKey = $this->goodsCacheKeyTag['limitUserNumKey'];
$hadGetGoodsMembers = $this->goodsCacheKeyTag['hadGetGoodsMembers'];
$goodsNumCacheKey = $this->goodsCacheKeyTag['goodsNumCacheKey'];
$redis = $this->redis;
// 每个用户最多抢1件商品
$hGGM = $redis->sIsMember($hadGetGoodsMembers, $uid);
if ($hGGM) {
return [
'status' => false,
'msg' => $uid . '每个人只能抢购1件商品'
];
}
// 超出限定人数说明已经抢购完
$res = $redis->incr($limitUserNumKey);
if ($res > $num) {
return [
'status' => false,
'msg' => $uid . '来晚一步啦, 商品已经抢空1'
];
}
// 商品已抢完
$goodsNum = $redis->get($goodsNumCacheKey);
if ($goodsNum >= $goodsN) {
return [
'status' => false,
'msg' => $uid . '来晚一步啦, 商品已经抢空2'
];
}
// TODO 查数据库验证用户身份
return ['status' => true];
}
}
相关推荐
laravel-cart:laravel 框架购物车组件
laravel-cart laravel 框架购物车组件 安装 可以直接在命令行安装: composer require "rayjun/laravel-cart:1.0.*" 或者可以在你项目的 composer.json "require": { "rayjun/laravel-cart": "1.0.*" } 然后执行: composer update 在完成上面的步骤之后,可以在 config/app.php 的 providers 数组中增加以下的代码: 'Rayjun\LaravelCart\LaravelCartServiceProvider' 然后增加下面一行到 aliases: 'Cart' => 'Rayjun\LaravelCart\Facades\Cart', 使用 获取一个购物车 Cart Cart::cart(int $user_id); 增加商品
laravel中redis发布与订阅
1.全局帮助方法 /** * redis command 执行 * Created by PhpStorm. * User: EricPan * Date: 2019/7/18 * Time: 14:08 * @param $key * @param $key_arr * @return mixed */ function redis_command($key,$key_arr)...
Laravel开发-promotion
Laravel开发-promotion Avored Laravel电子商务-促销模块
ElasticSearch ( 九 ) 订单操作实例
3 now-1h/d : now以毫秒为单位减一小时,向下舍入到天, 解析为: 2001-01-01 00:00:00。4 2001.02.01||+1M/d : 2001-02-01以毫秒为单位加一个月,向下舍入到天, 解析为: 2001-03-01 00:00:00。2 now-1h : now以毫秒为单位减一小时. 解析为: 2001-01-01 11:00:00。
【R】R画图不显示中文问题
系统mac os 11 RstutioVersion1.2.1335 RVersion3.6.2 画图里的中文一直显示成方框。 ggplot()+geom_point(aes(x=ta1$X2011年,y=ta1$X2012))+ xlab("2011年")+ylab("2021年") 解决方案: 使用showtext。 install.packages("showtext", repos = "https://mirrors.ustc.edu.cn/CRAN/") in...
强化学习 | Multi Agents | Trust Region | HATRPO | HAPPO
ICLR2022多智能体论文,将trust region推广到MA上,保证单调递增。学习博客,共7k字,纯手敲。含大量手写笔记。
laravel+Redis秒杀
原理 1.初始化: 秒杀商品,将商品以list数据类型存入redis(每个数量为一个元素); 2.购买: 1)购买用户入队列,如果用户队列长度超过指定的排队长度,则返回排队数过多。; 2)如果用户队列长度小于redis中商品长度(50),lpop从队列中取出商品,同时获取一个redis锁。然后生成订单,减去库存。下单完成 代码 MiaoshaController.php <?php namespace App\Http\Controllers; use App\Models\Goods; use
STM32HAL库 基于外部Flash+FatFs模拟U盘方式进行固件拷贝升级(详解)
STM32HAL库 基于外部Flash+FatFs模拟U盘方式进行固件拷贝升级
Elasticsearch:使用 Redis 让 Elasticsearch 更快
Elasticsearch 是一个强大的搜索引擎,可让你快速轻松地搜索大量数据。但是,随着数据量的增长,响应时间可能会变慢,尤其是对于复杂的查询。在本文中,我们将探讨如何使用 Redis 来加快 Elasticsearch 搜索响应时间。
SVDD和OCSVM的比较
OCSVM(one class support vector machine)即单类支持向量机,最先提出的文献为:Estimating the support of a high-dimensional distribution.该模型 将数据样本通过核函数映射到高维特征空间,使其具有更良好的聚集性,在特征空间中求解一个最优超平面实现目标数据与坐标原点的最大分离,如图1: 坐标原...
基于osgEarth的二维态势中时变对象的绘制方法
在态势系统中,卫星、飞机的轨迹、覆盖等的几何数据随时间改变,称之为时变对象。在以OSGEarth实现的二维态势中,如果利用OSGEarth的预定义线、面类型处理这种几何数据的动态改变,则导致效率极具降低。介绍了此问题并给出解决技巧。
laravel redis 在线用户_redis防止抢购商品超卖
前言:redis不仅仅是单纯的缓存,它还有一些特殊的功能,在一些特殊场景上很好用。本篇文用来测试下使用redis来防止抢购商品超卖问题。内容:使用redis的list进行测试 思路是设置一个redis列表List,假设有十个商品,每次请求先判断List的长度,小于十就能抢到商品,将用户信息存放到List中。代码如下//进行抢购 protected function way_list(...
【Unity】入门教程第一期-下载安装Unity编辑器(下)
讲解如何在Unity Hub中下载Unity编辑器以及IED环境
laravel redis_redis防止抢购商品超卖
前言:redis不仅仅是单纯的缓存,它还有一些特殊的功能,在一些特殊场景上很好用。本篇文用来测试下使用redis来防止抢购商品超卖问题。内容:使用redis的list进行测试 思路是设置一个redis列表List,假设有十个商品,每次请求先判断List的长度,小于十就能抢到商品,将用户信息存放到List中。代码如下//进行抢购 结果:失败!可以很明显数量不对顺序也不对。分析了下原因,在代码执...
GPOPSII 对控制量变化率进行约束,避免控制量振荡
在这篇文章中,在GPOPSII中通过对控制量变化的约束,优化求解得到更平滑的控制量曲线,更符合真实控制约束。
第1章 环境准备
本章是 Kubernetes 高可用集群部署的前置基础环境配置,所有节点必须严格按顺序执行。主要内容包括:节点规划(IP、角色、配置要求)、VMware 克隆节点环境清理(解决 MAC 地址和主机名冲突)、统一工作目录创建、主机名与 hosts 解析配置、系统基础升级、防火墙与 swap 关闭、内核模块加载(overlay、br_netfilter、ip_vs)、网络参数优化(IP 转发、桥接过滤)、时间同步配置等。Ubuntu 24.04 内核 6.8+ 原生支持 eBPF 和 IPVS,无需手动升级内核
redis抽奖并发_redis实现高并发下的抢购/秒杀功能
常规写法:查询出对应商品的库存,看是否大于0,然后执行生成订单等操作,但是在判断库存是否大于0处,如果在高并发下就会有问题,导致库存量出现负数这里我就只谈redis的解决方案吧...我们先来看以下代码(这里我以laravel为例吧)是否能正确解决超抢/卖的问题:$num = 10; //系统库存量$user_id = \Session::get('user_id');//当前抢购用户id$l...
SAP B1中文培訓教材_SDK
公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说
laravel redis_PHP 用redis做电商项目的秒杀功能
参与过抢购活动就知道,很明显的一点是即便商品实际没有了也是可以下单成功的,但是在支付的时候会提示你商品没有了。实现原理:list双向链表使用redis队列,因为pop操作是原子的,即使有很多用户同时到达,也是依次执行.(mysql事务在高并发下性能下降很厉害,文件锁的方式也是).此处用到了Redis中的链表(list)数据类型:‘栈’:从链表的头部添加元素,先进后出'队列’:从链表的尾部添加元素,...
jdk-8u144-linux-x64.tar.gz.
该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包
精雕软件(JDpaint) 5.5 绿色版
精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版
laravel简单秒杀实现
业务:平台推出商品秒杀活动,活动中可以添加多个商品,即同时有多个商品参与了秒杀,但每个人对同一个商品只能成功抢购一个,预计有1w人参加,即最高并发数10000。 思路:最常见的方法是使用reids来实现,创建两个队列,商品库存队列和抢购成功用户队列,用户抢购时,先判断用户是否在抢购成功用户队列中,是直接返回已抢购成功,否则从商品库存队列取出一个商品库存,取得成功将用户加入抢购成功用户队列,取出失...
jre9下载 jdk9
(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】
基于Thinkphp和Laravel框架的校园二手物品交易系统的设计与实现
本系统后端采用 PHP 语言搭配Thinkphp或者 Laravel 框架,PHP 语法简洁且功能强大,Laravel 或者Thinkphp框架能优化代码结构、提升开发效率,高效实现系统核心逻辑与数据库交互。前端运用 Vue 框架,其组件化开发与响应式设计,可打造流畅交互界面。MySQL 数据库稳定可靠,能安全存储海量文档数据,整体而言,这些成熟技术相互配合,能顺利完成系统开发。开发软件: hbuiderx,vscode、Adobe Dreamweaver等。
基于Thinkphp和Laravel电商平台网上商城---
本系统后端采用 PHP 语言搭配Thinkphp或者 Laravel 框架,PHP 语法简洁且功能强大,Laravel 或者Thinkphp框架能优化代码结构、提升开发效率,高效实现系统核心逻辑与数据库交互。前端运用 Vue 框架,其组件化开发与响应式设计,可打造流畅交互界面。MySQL 数据库稳定可靠,能安全存储海量文档数据,整体而言,这些成熟技术相互配合,能顺利完成系统开发。开发软件: hbuiderx,vscode、Adobe Dreamweaver等。
PHP 用redis做电商项目中的秒杀商品功能
参与过抢购活动就知道,很明显的一点是即便商品实际没有了也是可以下单成功的,但是在支付的时候会提示你商品没有了。 实现原理:list双向链表 使用redis队列,因为pop操作是原子的,即使有很多用户同时到达,也是依次执行.(mysql事务在高并发下性能下降很厉害,文件锁的方式也是). 此处用到了Redis中的链表(list)数据类型: ‘栈’:从链表的头部添加元素,先进后出 ‘队列’:从链表的...
揭秘PHP库存扣减痛点:如何用Redis+Lua实现毫秒级并发控制
解决高并发库存超卖难题,深入解析PHP在电商系统中的库存并发控制(Redis+Lua)实现方案。适用于秒杀、抢购等场景,通过Lua脚本原子操作Redis,确保数据一致性与毫秒级响应。高效、可靠,值得收藏。
421



被折叠的 条评论
为什么被折叠?



