IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> static 静态变量引起 Laravel 中队列一个 Bug -> 正文阅读

[PHP知识库]static 静态变量引起 Laravel 中队列一个 Bug

背景?

项目中有一个秒杀业务使用?Laravel 的队列进行对未付款超时的订单,进行库存回收处理

问题

????????未付款超时的订单库存没有及时回滚,造成了少卖的和用户不能买的情况(因为我们针对商品有限购处理,限购也没有及时重置)

?

环境

[root@vdevops XXXXXXXXApi]# php artisan --version
Laravel Framework 6.20.27
[root@vdevops XXXXXXXXApi]# php -v
PHP 7.4.19 (cli) (built: May  4 2021 11:06:37) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
[root@vdevops XXXXXXXXApi]# 

代码?

<?php

namespace App\Traits;
use App\Events\seckill\UserListCancle;
use App\Exceptions\InvalidRequestException;
use App\Models\SeckillGoods;
use Illuminate\Support\Facades\Redis;

trait Seckill
{
    private static $taskGoods;
    private static $todayTaskId;
    private static $ingNodeId;
    private static $nodeInfo;
    private static $node;
    private static $expiredBuy;
    private static $info;  

?????????从上面部分代码可以看到定义的是全局的静态成员变量,目的是为了避免在一段代码里重调用一个方法?,把结果缓存起来,提升代码运行效率

当排查问题时,一直以为是队列的进程服务挂掉啦,当重新启动队列服务后,库存回收服务就恢复正常,因为我们的秒杀业务是按天进行,所以等到第二天进行观测下,第二天又出现服务不能正常回收库存。

由此判定不是这里的问题,通过代码追查到还原库存的 recoveSeckillGoodsStock function 获取秒杀业务当天的 $todayTaskId 使用的是静态成员变量调用的,Laravel 的队列是常驻内存,采用CLI运行模式在后台运行,直到进程被杀死,否则代码不会更新。$todayTaskId的值一直启动队列那天时间的秒杀任务ID ,始终没有发生变化,所以导致还原库存服务一直不成功的bug。

?

静态变量

????????如果一个函数内定义的变量前使用关键字 static 来声明,那么该变量就是静态变量。一般函数内的变量在函数调用结束后,其存储的数据将被清除,所占的内存空间也被释放。而使用静态变量时,该变量会在函数第一次被调用时被初始化,初始化后该变量也不会被清除,当再次调用该函数时,这个静态变量不再被初始化,而能保存上次函数执行完后的值。可以说静态变量在所有对该函数的调用之间共享。

  • 如果在函数中?unset()?一个静态变量,那么在函数内部此静态变量将被销毁。但是,当再次调用此函数时,此静态变量将被复原为上次被销毁之前的值。
  • 直接给静态变量赋值null 就可以

变量范围的另一个重要特性是静态变量(static variable)。静态变量仅在局部函数域中存在,但当程序执行离开此作用域时,其值并不丢失。看看官网下面的例子:https://www.php.net/manual/zh/language.variables.scope.php

?

总结

????????使用静态成员变量需注意使用场景,也忽略 Laravel 的队列是常驻内存,如果是正常用户在前端访问秒杀页面,使用静态成员变量当缓存是可以的,因为PHP的常用运行环境是php-fpm模式,每次请求结束进程就会被回收, 静态变量不会常驻内存(只会在此次请求生效) 。

还一点就是代码没有跟着业务和场景的不同进行代码隔离,还原库存的function 和前端页面访问的方法都在一个特性Traits里,?开发功能时就会造成疏忽,导致一些问题的出现。

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-11-22 12:08:09  更:2021-11-22 12:08:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/14 14:39:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码