在ThinkPHP8中使用Redis队列,你可以使用内置的think\queue
库。以下是一个简单的例子,展示了如何将任务推送到Redis队列以及如何处理队列中的任务。
首先,确保你已经安装并配置了Redis服务器。
安装Redis扩展(如果尚未安装): composer require predis/predis
配置队列驱动,在
config/queue.php
中设置:
phpreturn [ // 驱动类型:sync、database、redis 'default' => 'redis', 'connections' => [ // 同步执行 'sync' => [ 'type' => 'sync', ], // 数据库驱动 'database' => [ 'type' => 'database', 'queue' => 'default', 'table' => 'jobs', 'connection' => null, ], // Redis驱动 'redis' => [ 'type' => 'redis', 'queue' => 'default', 'host' => Env::get('cache.host', '127.0.0.1'), 'port' => Env::get('cache.port', 6379), 'password' => Env::get('cache.password', ''), 'select' => 1, 'timeout' => 0, 'persistent' => false, 'expire' => 0, ], ], 'failed' => [ 'type' => 'none', 'table' => 'jobs_failed', ], ];
创建一个任务类,例如app\job\ExampleJob
:
php
<?php
namespace app\job;
use app\migrate\service\SunshineEvaluationService;
use think\queue\Job;
use think\facade\Log;
/**
* 队列 --
*/
class SyncMaidoThreePcJob
{
public function fire(Job $job, $data)
{
// 记录日志
$this->log($data);
// 这里执行具体的任务
try{
if(!empty($data['house_id']) && !empty($data['type'])){
if($data['type'] == "landscape"){
SunshineEvaluationService::syncLandscape($data['house_id']);
}elseif($data['type'] == "noise"){
SunshineEvaluationService::syncNoise($data['house_id']);
}elseif($data['type'] == "sunshine"){
SunshineEvaluationService::syncSunshine($data['house_id']);
}elseif($data['type'] == "all"){
SunshineEvaluationService::sync($data['house_id']);
}
}
}catch (\Exception $e){
// $job->delete();
var_dump($e->getMessage());
}
//.......
// 通过这个方法可以检查这个任务已经重试了几次了
if ($job->attempts() > 3) {
}
// 如果任务执行成功后 记得删除任务,不然这个任务会重复执行,直到达到最大重试次数后失败后,执行failed方法
$job->delete();
// 也可以重新发布这个任务
// $job->release($delay); //$delay为延迟时间
}
public function failed($data)
{
// 任务达到最大重试次数后,失败了
}
public function log($data)
{
Log::write($data, 'queue');
}
}
推送任务到队列:
php
use think\facade\Queue;
$jobData = ['house_id'=>$houseid,'type'=>"sunshine"];
Queue::push('app\job\SyncMaidoThreePcJob@fire', ['house_id'=>$houseid,'type'=>"sunshine"], 'SyncMaidoThreePcJob');
启动队列监听器(通常在后台运行):
work 命令是单进程的处理模式。
按照是否设置了 --daemon
参数,work命令又可分为单次执行和循环执行两种模式。
- 单次执行:不添加
--daemon
参数,该模式下,work进程在处理完下一个消息后直接结束当前进程。当队列为空时,会sleep一段时间然后退出。 - 循环执行:添加了
--daemon
参数,该模式下,work进程会循环地处理队列中的消息,直到内存超出参数配置才结束进程。当队列为空时,会在每次循环中sleep一段时间。
php think queue:work redis --once --queue=SyncMaidoThreePcJob --delay=0 --memory=256 --sleep=10 --tries=3
-
--queue
:指定要处理的队列名称。这是必须的参数,用于告诉工作进程应该从哪个队列中获取任务进行处理。例如,--queue helloJobQueue
指定了工作进程应该从名为helloJobQueue
的队列中获取任务。 -
-- once: 这个命令是用于执行PHP ThinkPHP框架中的队列任务的。在这个命令中,我们使用Redis作为队列驱动,并且我们只运行一次工作进程。
-
--daemon
:是否以守护进程模式运行。如果加上此参数,工作进程将循环执行,处理完一个消息后不会立即退出,而是继续等待并处理下一个消息。如果不加该参数,处理完下一个消息后,进程将退出。 -
--delay
:如果本次任务执行抛出异常且任务未被删除时,设置其下次执行前延迟多少秒,默认为0。这可以用于控制任务的失败重试间隔。 -
--force
:系统处于维护状态时是否仍然处理任务。此参数的说明在提供的资料中并未找到,可能需要根据实际使用情况进行解释或设置。 -
--memory
:该进程允许使用的内存上限,以M为单位。这可以控制每个工作进程使用的最大内存量,以避免内存溢出。 -
--sleep
:如果队列中无任务,则sleep多少秒后重新检查(work+daemon模式)或者退出(listen或非daemon模式)。这是控制工作进程在空闲时的行为,如果没有任务可处理,它将会休眠一段时间后再检查队列。 -
--tries
:如果任务已经超过尝试次数上限,则触发'任务尝试次数超限'事件,默认为0。这可以用于控制任务的最大尝试次数,超过该次数后,任务将被视为失败。
php think queue:listen
命令是用来监听队列任务的。
-
listen 命令是 双进程 + 管道 的处理模式。
listen命令所在的进程会循环地创建 单次执行模式的 work 进程,每次创建的 work 进程只消费一个消息就会结束, 然后 listen 进程再创建一个新的 work 进程,
- listen 进程会定时检查当前的 work 进程执行时间是否超过了 --timeout 参数的值, 如果已超时, 则 listen 进程会 kill 掉 work 进程, 然后抛出异常
- listen 进程会通过管道来监听当前的 work 进程的输出, 当 work 进程有输出时, listen 进程会将输出写入到 stdout / stderr
- listen 进程会定时通过
proc_get_status()
来监控当前的 work 进程是否仍在运行, work 进程消费完一个任务之后, work 进程就结束了,其状态会变成 terminated, 此时 listen 进程就会重新创建一个新的 work 进程并对其计时, 新的 work 进程开始消费下一个任务
php think queue:listen --queue SyncMaidoThreePcJob --memory=256 --sleep=10 --tries=3
参数可以是:
-
--queue
指定监听的队列名称。 -
--daemon
以守护进程模式运行,会持续监听并处理队列任务。 -
--delay
设置任务失败重试前的延迟时间(秒)。 -
--force
强制执行,即使任务类不存在。 -
--memory
设置最大内存使用限制,超出将退出(单位为MB)。 -
--sleep
当没有任务时,轮询间隔时间(秒)。 -
--tries
设置任务尝试次数。