think-queue操作redis实现延时任务(实现简单)

本文介绍了在项目流量增加时,为何选择使用Think-Queue实现延时任务而非定时任务,以及详细的安装、配置和使用步骤。作者比较了Redis过期回调、RabbitMQ等其他方法,并强调了Think-Queue对中小型项目的适用性。
摘要由CSDN通过智能技术生成


前言

刚开始接触的项目流量小,延时关闭订单都是用的定时任务这种,访问量低,数据库压力不大。后面发现访问量高了以后定时任务对数据库压力太大了,不建议使用这种方法,所以我看了下think-queue实现延时任务的实现方法,并自己使用测试了。
下面就是具体实现方法步骤,特别简单。


一、为什么要用延时队列?

(1)最开始我用的都是定时任务(数据库轮询)。服务器搞个定时任务,几分钟跑一次。例如延迟关闭订单,去查询数据库全部待支付订单,然后把超过30分钟未支付的订单关闭。
优点:实现太简单了。
缺点:轮询时间间隔不好确定,占用服务器资源,影响数据库性能。数据库的压力会很大,尤其是订单表数目和用户大了以后,除非极个别情况,不然不建议使用(看了博客上面说的)。
我看了几个方法,对比一下其中的优劣,结合项目实际情况选择了think-queue。
(2)Redis过期回调,利用Redis的key过期回调事件,也能够实现。
我没选择他的主要原因是,一开始我觉得订阅事件会很消耗服务器性能,还有就是要修改Redis的配置,重启服务器。我们服务器挂了好多乱七八糟的项目,还有一些服务任务啥的,我担心有影响。后面看了《请勿过度依赖 Redis 的过期监听》这篇文章,才发现缺点挺致命。
Redis 不能确保 key 在指定时间被删除 , 会造成通知的延期 。
“Basically expired events are generated when the Redis server deletes the key and not when the time to live theoretically reaches the value of zero.”
(3)RabbitMQ的消息队列。这个思路其实跟我要用的Redis的zset有序集合差不多。
消息在发送到消息队列服务端后并不会立马投递,而是根据消息中的属性延迟固定时间后才投递给消费者。
这个优缺点明显,优点:高效,好扩展,支持分布式,换言之就是访问高的大型项目肯定是用这个,面试也会问。
缺点:实现比前面的复杂,维护成本高。
(4)Redis的zset有序集合。
这个是在网上查到的。感觉特别简单,容易实现,对中小型项目友好。具体思路是加入一个延时队列,设置延迟时间执行。这块实现很容易,然后发布监听也很容易,于是我就用了。

二、使用步骤

1.安装Redis

服务器我用的是宝塔,所以很简单。根据自己环境安装。
要配置一下密码。

2.安装think-queue

这里我用的composer。

composer require topthink/think-queue

3.修改配置文件

我是tp6的项目,composer安装完,会在config目录下面生成queue.php的文件。
修改一下配置:

return [
    'default'     => 'redis', // 默认改成Redis
    'connections' => [
        'sync'     => [
            'type' => 'sync',
        ],
        'database' => [
            'type'       => 'database',
            'queue'      => 'default',
            'table'      => 'jobs',
            'connection' => null,
        ],
        'redis'    => [
            'type'       => 'redis',
            'queue'      => 'default', // 这个后面讲监听会说明
            'host'       => '127.0.0.1',
            'port'       => 6379, // 端口
            'password'   => '你的Redis密码',
            'select'     => 0,
            'timeout'    => 0,
            'persistent' => false,
        ],
    ],
    'failed'      => [
        'type'  => 'none',
        'table' => 'failed_jobs',
    ],
];

4. 写延时任务代码

在app目录下新建一个queue文件夹,然后创建一个类文件,我这里起名Order,操作订单的。

/**
 * @param Job $job
 * @param $order_id
 * @return void
 * 订单超时取消
 */
public function closeOrder(Job $job, $order_id)
{
    $order = (new \app\model\Order())->getInfo($order_id, 2);  // 查询当前订单是否为未支付状态
    if ($order->isEmpty()) {
        $job->delete();  // 非未支付状态,删除执行任务
    } else {
        $result = (new \app\model\Order())->overtime($order_id);  // 更新订单状态为已关闭
        if ($result) {
            $job->delete();  //关闭成功,删除执行任务
        } else {
            if ($job->attempts() > 3) {
                $job->delete();  // 累计执行3次均失败,删除执行任务
            } else {
                $job->release(10);  // 间隔10秒执行一次
            }
        }
    }
}

5.生产者发布延时任务

代码如下(示例):

public function createOrder()
{
	// 创建订单业务代码
	Queue::later(30 * 60, 'app\queue\Order@closeOrder', $order['id']);  //加入队列,并延迟关闭时间执行
}

6.写入延迟任务后看一下Redis,是否写入数据

我本来是想找Redis查看工具的,没找到可用的,官方没有,我用的宝塔。能用的被下了,所以只能在这看。多捞啊。
Redis数据库查看

7.开启进程,监听延时任务

使用php think queue:listen开启监听服务。把延迟任务设置短点,比如一分钟,过一会就能看到执行了。
我们不可能一直在服务器终端这样开启服务,所以必须要设置守护进程。
我使用的是宝塔面板,根据自己环境查找对应的服务,设置守护进程,让监听一直开着。我不太清楚这块占用服务器性能如何,知道方法后测试看看。
宝塔软件商店直接搜进程守护管理器,就找到了。
这个是宝塔守护进程的插件名字
配置进程守护
名称这里随便起,启动用户默认root即可。启动命令填“php think queue:listen”即可。进程目录选择你的项目的根目录就行。比如你项目是test,就填“/www/wwwroot/test/”。备注也是随便写。
启动命令如果填写“php think queue:listen – queue”需要再-- queue 后面加名称,而且要在queue.php文件里面修改'queue' => 'default', // 这个后面讲监听会说明'queue' => 'test', // test改为你想执行的队列名称。完整命令就是php think queue:listen -- queue test

可以在这查看执行日志。

日志查看


总结

这个方法非常简单,适用于中小型项目,但是超大访问的分布式的项目还是要RabbitMQ、Kafka这种框架。后续学习再继续研究。有问题可以留言,我这边测试是OK的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coding-雷欧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值