在ThinkPHP 6框架中使用Redis处理高并发场景,通常涉及到缓存、分布式锁、队列等技术。以下是一个结合这些技术的完整示例代码,以处理一个简单的商品秒杀场景为例

本文介绍了如何在ThinkPHP6项目中配置Redis作为缓存驱动,并利用其实现分布式锁,以及在秒杀场景中使用消息队列进行异步处理的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设已安装并配置好ThinkPHP 6及Redis扩展。

1. 安装依赖

确保已安装topthink/think-queue(用于消息队列)和topthink/framework(ThinkPHP 6核心包):

composer require topthink/think-queue topthink/framework

2. 配置Redis

config/cache.php中配置Redis作为默认缓存驱动:

return [
    // ...
    'default' => 'redis',
    'stores' => [
        'redis' => [
            'type' => '\think\cache\driver\Redis',
            'host' => '127.0.0.1',
            'port' => 6379,
            // ... 其他配置项如密码、数据库索引等
        ],
    ],
];

3. 创建模型、控制器、中间件

  • app/model/Product.php(商品模型)
namespace app\model;

use think\Model;

class Product extends Model
{
    protected $table = 'products';

    public static function decreaseStock(int $productId, int $quantity)
    {
        self::where('id', $productId)->dec('stock', $quantity)->update();
    }
}

 

  • app/controller/SeckillController.php(秒杀控制器)

 

namespace app\controller;

use app\model\Product;
use think\Request;
use think\Queue;
use think\response\Json;

class SeckillController extends BaseController
{
    public function seckill(Request $request)
    {
        $productId = $request->param('product_id');
        $userId = $request->param('user_id');

        if (!self::tryLock($productId)) {
            return Json::create(['status' => 'failed', 'message' => '系统繁忙,请稍后重试']);
        }

        try {
            $success = self::handleSeckill($productId, $userId);
            if ($success) {
                return Json::create(['status' => 'success', 'message' => '秒杀成功']);
            } else {
                return Json::create(['status' => 'failed', 'message' => '秒杀失败,请稍后重试']);
            }
        } finally {
            self::unlock($productId);
        }
    }

    private function tryLock(int $productId): bool
    {
        // 使用Redis实现分布式锁,这里简化为使用setnx模拟
        $redis = \think\facade\Cache::store('redis')->handler();
        $lockKey = 'seckill_lock_' . $productId;
        return $redis->setnx($lockKey, time());
    }

    private function unlock(int $productId): void
    {
        // 使用Redis释放分布式锁,这里简化为删除键模拟
        $redis = \think\facade\Cache::store('redis')->handler();
        $lockKey = 'seckill_lock_' . $productId;
        $redis->del($lockKey);
    }

    private function handleSeckill(int $productId, int $userId): bool
    {
        // 假设已从缓存中获取到商品剩余库存
        $remainingStock = self::getRemainingStockFromCache($productId);

        if ($remainingStock <= 0) {
            return false;
        }

        // 减库存、创建订单等业务逻辑
        Product::decreaseStock($productId, 1);

        // 发送队列任务,如发送通知、更新用户状态等
        Queue::push(new SeckillSuccessJob([
            'product_id' => $productId,
            'user_id' => $userId,
        ]));

        return true;
    }

    private function getRemainingStockFromCache(int $productId): int
    {
        // 省略从缓存中获取剩余库存的逻辑,实际应用中应从Redis中获取
        return 10; // 假设剩余库存为10
    }
}

4. 创建消息队列任务

  • app/jobs/SeckillSuccessJob.php(秒杀成功后的异步任务)
namespace app\jobs;

use think\queue\Job;
use think\facade\Log;

class SeckillSuccessJob
{
    public function __construct(array $data)
    {
        $this->data = $data;
    }

    public function handle(Job $job, $data)
    {
        // 这里实现异步任务逻辑,如发送通知、更新用户状态等

        // 完成任务后删除
        $job->delete();
    }

    public function failed(\Throwable $exception)
    {
        Log::error('SeckillSuccessJob failed: ' . $exception->getMessage());
    }
}

 5. 配置并启动消息队列

config/queue.php中配置消息队列驱动(如rabbitmqredis等)。然后启动队列监听器:

php think queue:listen --queue=seckill_queue

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值