laravel+redis实现的抢购(待优化)

laravel 中使用 elasticsearch 安装 elasticsearch 和 kibana(用来查看管理elasticsearch中的数据) 参照:https://blog.youkuaiyun.com/z_ruitao/article/details/105043521 安装 scout composer require laravel/scout # 在config/app.php 的 providers 数组中添加 Laravel\Scout... 阅读详情
<?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];
    }


}
redis实现高并发下的抢购/秒杀功能 redis实现高并发下的抢购/秒杀功能A代码B分析C分析D分析E分析A-F改好的代码 抢购/秒杀是如今很常见的一个应用场景,那么高并发竞争下如何解决超抢(或超卖库存不足为负数的问题)呢? 常规写法: 查询出对应商品的库存,看是否大于0,然后执行生成订单等操作,但是在判断库存是否大于0处,如果在高并发下就会有问题,导致库存量出现负数 这里我就只谈redis的解决方案吧… 我们先来看以下代码(这里我以laravel为例吧)是否能正确解决超抢/卖的问题: A代码 <?php $num = 10; # 系 阅读详情

相关推荐

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)...

qq_29755359的博客 421

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。

yuanchun的知识整理 898

【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...

weixin_41772125的博客 1万+

强化学习 | Multi Agents | Trust Region | HATRPO | HAPPO

ICLR2022多智能体论文,将trust region推广到MA上,保证单调递增。学习博客,共7k字,纯手敲。含大量手写笔记。

111辄的博客 1万+

laravel+Redis秒杀

原理 1.初始化: 秒杀商品,将商品以list数据类型存入redis(每个数量为一个元素); 2.购买: 1)购买用户入队列,如果用户队列长度超过指定的排队长度,则返回排队数过多。; 2)如果用户队列长度小于redis中商品长度(50),lpop从队列中取出商品,同时获取一个redis锁。然后生成订单,减去库存。下单完成 代码 MiaoshaController.php <?php namespace App\Http\Controllers; use App\Models\Goods; use

lion的博客 1027

STM32HAL库 基于外部Flash+FatFs模拟U盘方式进行固件拷贝升级(详解)

STM32HAL库 基于外部Flash+FatFs模拟U盘方式进行固件拷贝升级

qq_36075612的博客 1万+

Elasticsearch:使用 Redis 让 Elasticsearch 更快

Elasticsearch 是一个强大的搜索引擎,可让你快速轻松地搜索大量数据。但是,随着数据量的增长,响应时间可能会变慢,尤其是对于复杂的查询。在本文中,我们将探讨如何使用 Redis 来加快 Elasticsearch 搜索响应时间。

Elastic 中国社区官方博客 3715

SVDD和OCSVM的比较

OCSVM(one class support vector machine)即单类支持向量机,最先提出的文献为:Estimating the support of a high-dimensional distribution.该模型 将数据样本通过核函数映射到高维特征空间,使其具有更良好的聚集性,在特征空间中求解一个最优超平面实现目标数据与坐标原点的最大分离,如图1: 坐标原...

qq_33880788的博客 1万+

基于osgEarth的二维态势中时变对象的绘制方法

在态势系统中,卫星、飞机的轨迹、覆盖等的几何数据随时间改变,称之为时变对象。在以OSGEarth实现的二维态势中,如果利用OSGEarth的预定义线、面类型处理这种几何数据的动态改变,则导致效率极具降低。介绍了此问题并给出解决技巧。

eyepeak的博客 2090

laravel redis 在线用户_redis防止抢购商品超卖

前言:redis不仅仅是单纯的缓存,它还有一些特殊的功能,在一些特殊场景上很好用。本篇文用来测试下使用redis来防止抢购商品超卖问题。内容:使用redis的list进行测试    思路是设置一个redis列表List,假设有十个商品,每次请求先判断List的长度,小于十就能抢到商品,将用户信息存放到List中。代码如下//进行抢购 protected function way_list(...

weixin_33089993的博客 341

【Unity】入门教程第一期-下载安装Unity编辑器(下)

讲解如何在Unity Hub中下载Unity编辑器以及IED环境

Xiaoxin的博客 2042

laravel redis_redis防止抢购商品超卖

前言:redis不仅仅是单纯的缓存,它还有一些特殊的功能,在一些特殊场景上很好用。本篇文用来测试下使用redis来防止抢购商品超卖问题。内容:使用redis的list进行测试    思路是设置一个redis列表List,假设有十个商品,每次请求先判断List的长度,小于十就能抢到商品,将用户信息存放到List中。代码如下//进行抢购 结果:失败!可以很明显数量不对顺序也不对。分析了下原因,在代码执...

weixin_39600331的博客 365

GPOPSII 对控制量变化率进行约束,避免控制量振荡

在这篇文章中,在GPOPSII中通过对控制量变化的约束,优化求解得到更平滑的控制量曲线,更符合真实控制约束。

Dannyfomer的博客 1871

第1章 环境准备

本章是 Kubernetes 高可用集群部署的前置基础环境配置,所有节点必须严格按顺序执行。主要内容包括:节点规划(IP、角色、配置要求)、VMware 克隆节点环境清理(解决 MAC 地址和主机名冲突)、统一工作目录创建、主机名与 hosts 解析配置、系统基础升级、防火墙与 swap 关闭、内核模块加载(overlay、br_netfilter、ip_vs)、网络参数优化(IP 转发、桥接过滤)、时间同步配置等。Ubuntu 24.04 内核 6.8+ 原生支持 eBPF 和 IPVS,无需手动升级内核

幸福街--linux技术分享 211

redis抽奖并发_redis实现高并发下的抢购/秒杀功能

常规写法:查询出对应商品的库存,看是否大于0,然后执行生成订单等操作,但是在判断库存是否大于0处,如果在高并发下就会有问题,导致库存量出现负数这里我就只谈redis的解决方案吧...我们先来看以下代码(这里我以laravel为例吧)是否能正确解决超抢/卖的问题:$num = 10; //系统库存量$user_id = \Session::get('user_id');//当前抢购用户id$l...

weixin_39743064的博客 363

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

laravel redis_PHP 用redis做电商项目的秒杀功能

参与过抢购活动就知道,很明显的一点是即便商品实际没有了也是可以下单成功的,但是在支付的时候会提示你商品没有了。实现原理:list双向链表使用redis队列,因为pop操作是原子的,即使有很多用户同时到达,也是依次执行.(mysql事务在高并发下性能下降很厉害,文件锁的方式也是).此处用到了Redis中的链表(list)数据类型:‘栈’:从链表的头部添加元素,先进后出'队列’:从链表的尾部添加元素,...

weixin_39755712的博客 203

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来实现,创建两个队列,商品库存队列和抢购成功用户队列,用户抢购时,先判断用户是否在抢购成功用户队列中,是直接返回已抢购成功,否则从商品库存队列取出一个商品库存,取得成功将用户加入抢购成功用户队列,取出失...

m0_38143375的博客 1386

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等。

mind526的博客 790

基于Thinkphp和Laravel电商平台网上商城---

本系统后端采用 PHP 语言搭配Thinkphp或者 Laravel 框架,PHP 语法简洁且功能强大,Laravel 或者Thinkphp框架能优化代码结构、提升开发效率,高效实现系统核心逻辑与数据库交互。前端运用 Vue 框架,其组件化开发与响应式设计,可打造流畅交互界面。MySQL 数据库稳定可靠,能安全存储海量文档数据,整体而言,这些成熟技术相互配合,能顺利完成系统开发。开发软件: hbuiderx,vscode、Adobe Dreamweaver等。

QQ242219979的博客 609

PHP 用redis做电商项目中的秒杀商品功能

参与过抢购活动就知道,很明显的一点是即便商品实际没有了也是可以下单成功的,但是在支付的时候会提示你商品没有了。 实现原理:list双向链表 使用redis队列,因为pop操作是原子的,即使有很多用户同时到达,也是依次执行.(mysql事务在高并发下性能下降很厉害,文件锁的方式也是). 此处用到了Redis中的链表(list)数据类型: ‘栈’:从链表的头部添加元素,先进后出 ‘队列’:从链表的...

qq_26282869的博客 578

揭秘PHP库存扣减痛点:如何用Redis+Lua实现毫秒级并发控制

解决高并发库存超卖难题,深入解析PHP在电商系统中的库存并发控制(Redis+Lua)实现方案。适用于秒杀、抢购等场景,通过Lua脚本原子操作Redis,确保数据一致性与毫秒级响应。高效、可靠,值得收藏。

PixelGlow的博客 1079
上一篇: 一次成功的snoopy模拟登录体验
下一篇: php骚函数
小Z笔记
博客等级 码龄9年 11粉丝 54原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值