You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
aquaculture/app/Console/Commands/DelExpireSecKill.php

97 lines
3.7 KiB

<?php
namespace App\Console\Commands; // 定义命名空间
use App\Models\Seckill; // 引入 Seckill 模型
use Carbon\Carbon; // 引入 Carbon 日期处理库
use Illuminate\Console\Command; // 引入 Laravel 的 Command 基类
use Illuminate\Support\Facades\Redis; // 引入 Redis 门面
/**
* 删除过期秒杀数据控制台命令
*
* 该命令用于删除过期的秒杀数据,并将相关库存数量回滚到商品中。
*/
class DelExpireSecKill extends Command
{
/**
* 控制台命令的名称和签名
*
* @var string
*/
protected $signature = 'moon:del-seckills'; // 定义命令的名称和签名
/**
* 控制台命令的描述
*
* @var string
*/
protected $description = 'delete expire seckills'; // 描述该命令的用途
/**
* 创建一个新的命令实例.
*
* @return void
*/
public function __construct()
{
parent::__construct(); // 调用父类构造函数
}
/**
* 执行控制台命令
*
* 该方法执行删除过期秒杀数据的逻辑,并回滚相关库存。
*
* @return mixed
*/
public function handle()
{
$rollbacks = collect(); // 创建一个集合,用于存储回滚的秒杀记录
// 查出已经过期且没有回滚过的秒杀
Seckill::query()
->where('is_rollback', 0) // 选择未回滚的秒杀
->where('end_at', '<', Carbon::now()->toDateTimeString()) // 选择已过期的秒杀
->get() // 获取符合条件的秒杀记录
->map(function (Seckill $seckill) use ($rollbacks) {
// 1. 回滚数量到商品
// 2. 设置为过期
$product = $seckill->product()->first(); // 获取与秒杀相关联的商品
// 获取 Redis 中的秒杀数量
$jsonSeckill = Redis::get($seckill->getRedisModelKey()); // 从 Redis 获取秒杀数据
$redisSeckill = json_decode($jsonSeckill, true); // 将 JSON 数据解码为数组
// 获取剩余的秒杀量
$surplus = Redis::llen($seckill->getRedisQueueKey()); // 从 Redis 获取剩余秒杀量
// 恢复剩余的库存量
// 恢复库存数量
if ($redisSeckill['sale_count'] != 0) { // 如果 Redis 中的销售数量不为零
$product->increment('sale_count', $redisSeckill['sale_count']); // 增加商品的销售数量
}
if ($surplus != 0) { // 如果剩余秒杀量不为零
$product->increment('count', $surplus); // 增加商品的总库存数量
}
// 同步 Redis 数据到数据库中
$seckill->sale_count += $redisSeckill['sale_count']; // 更新秒杀的销售数量
$seckill->rollback_count += $surplus; // 更新秒杀的回滚数量
$seckill->is_rollback = 1; // 标记为已回滚
$seckill->save(); // 保存更新后的秒杀记录
$rollbacks->push($seckill); // 将已回滚的秒杀记录添加到集合中
// 删除掉秒杀数据
$ids = Redis::connection()->keys("seckills:{$seckill->id}:*"); // 获取与秒杀相关的所有 Redis 键
Redis::del($ids); // 删除这些 Redis 键
});
if ($rollbacks->isNotEmpty()) { // 如果有回滚的秒杀记录
createSystemLog('系统回滚秒杀数据', $rollbacks->toArray()); // 记录系统回滚操作的日志
}
}
}