最终目标
我的应用程序的目标是向 Redis 队列发送大量电子邮件(此功能有效),然后 Redis 将这些电子邮件的处理限制为每隔选定的分钟数仅处理一定数量的电子邮件。
对于此示例,我有一个将时间附加到文件的测试作业,我试图将其限制为每 60 秒一次。
到目前为止的故事......
到目前为止,我的应用程序已成功将 50 个作业的测试数量推送到 Redis 队列。我可以登录到 Horizon 并在“processjob”队列中看到这 50 个作业。我也可以登录redis-cli,在列表键“queues:processjob”下看到50组。
我的问题是,一旦我尝试打开 throttle ,只有 1 个作业运行,其余作业失败并出现以下错误:
Predis\Response\ServerException: ERR Error running script (call to f_29cc07bd431ccbf64637e5dcb60484560fdfa2da): @user_script:10: WRONGTYPE Operation against a key holding the wrong kind of value in /var/www/html/smhub/vendor/predis/predis/src/Client.php:370
如果我取消限制,所有工作文件和 5 个作业都会立即运行。
我认为可能是键名不正确,但如果我更改以下内容:
public function handle()
{
//
Redis::throttle('queues:processjob')->allow(1)->every(60)->then(function(){
Storage::disk('local')->append('testFile.txt',date("Y-m-d H:i:s"));
}, function (){
return $this->release(10);
});
}
为此:
public function handle()
{
//
Redis::funnel('queues:processjob')->limit(1)->then(function(){
Storage::disk('local')->append('testFile.txt',date("Y-m-d H:i:s"));
}, function (){
return $this->release(10);
});
}
然后一切正常。
我的想法...
有些事情告诉我,问题是 redis 键的类型是“列表”,并且作业都在一个列表下。也就是说,如果它不以这种方式工作,我们将如何限制队列,因为限制需要一个唯一的 key 。
最佳答案
对于在尝试使其正常工作时遇到问题并且遇到与我相同的问题的任何其他人,这就是解决我的问题的方法:
错误
我假设 Redis::throttle('queues:processjob')
是指您想要限制的队列。然而,在重新阅读文档和测试代码之后,我意识到情况并非如此。
修复
Redis::throttle('queues:processjob')
旨在指向它自己的“持有”队列,因此必须是唯一的 Redis 键名。因此,将其更改为 Redis::throttle('throttle:queues:processjob')
对我来说效果很好。
工作原理
当我第一次研究这个问题时,我假设 Redis::throttle('this')
限制了您指定的队列。在某种程度上这是正确的,但如果工作是通过其他方式创建的,它将不起作用。
Redis::throttle('this')
实际上创建了一个新的“保持”队列,作业将在其中运行,直到满足您指定的条件。因此,在此示例中,作业将进入队列“this”,并且在释放 throttle 触发器时,它们将被传递到在其执行代码中指定的队列。在这种情况下,'queues:processjob'。
希望对您有所帮助!
关于尝试使用 throttle 时,Laravel 作业在 Redis 上失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52647839/