在实际项目开发中,我们经常会遇到需要轻量级队列的情况,比如发送短信,发送邮件等,这些任务使用kafka、RabbitMQ等重量级消息队列是不够的,但是它们是Functions比如异步、重试、并发控制确实是需要的。一般来说,我们经常使用Redis、Beanstalk、AmazonSQS来实现相关功能。Laravel为不同的后台队列服务提供了统一的API。本文将介绍使用最广泛的redis队列。在讲解laravel的队列服务之前,先说说基于redis的队列服务。首先,redis在设计上是作为缓存使用的,但是因为自身的特点,可以作为消息队列来使用。Redis队列的数据结构是List链表。redis作为消息队列的特点,比如FIFO(先进先出),很容易实现。您只需要一个列表对象来从开头获取数据并从结尾填充数据。相关命令:(1)左输入右输出:lpush/rpop;(2)右输入左输出:rpush/lpop。这个简单的消息队列很容易实现。ZsetOrderedcollection有些任务场景并不要求任务立即执行,而是需要延迟执行;有些任务非常重要,需要在任务失败时重试。单靠列表是无法完成这些功能的。这时候就需要redis的有序集合。Redis有序集合类似于Redis集合,是不包含相同字符串的集合。它们的区别在于,有序集中的每个成员都关联了一个分数score,用于对有序集中的成员从最低分到最高分进行排序。只看有序集与延迟任务无关,但是可以将有序集的分数设置为延迟任务启动的时间,然后轮询有序集取出过期的任务进行处理,从而实现了延迟任务的功能。对于需要重试的重要任务,在任务执行之前,会将任务放入有序集合中,并设置任务的最长执行时间。如果任务执行成功,任务将在有序集中删除。如果任务没有在指定时间内完成,那么有序的任务集将被放回队列中。相关命令:(1)ZADD将一个或多个成员添加到有序集合中,或者如果它已经存在则更新它的分数。(2)ZRANGEBYSCORE按分数返回成员范围的有序集合。(3)ZREMRANGEBYRANK删除给定索引内所有成员的有序集合。laravel队列服务的任务调度队列服务的任务调度过程如下:laravel的队列服务由两个进程控制,一个是生产者,一个是消费者。这两个进程操作redis的三个队列,其中一个是List,负责立即任务,两个Zset,分别负责延迟任务和待处理任务。生产者负责将任务推送到redis。如果是即时任务,则默认推送到queue:default;如果是延迟任务,会被推送到queue:default:delayed。消费者轮询两个队列,不断从队列中取出任务,先将任务放入queue:default:reserved,然后执行相关任务。如果任务执行成功,queue:default:reserved中的任务会被删除,否则会放回queue:default:delayed中。laravel队列服务任务分发流程的整体流程:任务处理器操作:创建任务队列设置'redis'=>['driver'=>'redis','connection'=>'default','queue'=>'default'','retry_after'=>90,]],在config/queue.php中配置一般redis默认配置如上,connection为redis在数据库中的连接名;queue是redis中的队列名,值得注意的是,如果你使用的是redis集群,需要使用keyhash标签,即{default};当任务运行时间超过retry_after时,任务将被放回队列中。任务类的创建任务类的结构很简单,一般只包含队列的句柄方法来调用这个任务。如果你想将任务推送到队列而不是同步执行它们,你需要实现IlluminateContractsQueueShouldQueue接口。如果要将任务推送到特定的连接,比如redis或者sqs,需要设置conneciton变量。如果要将任务推送到特定队列,可以设置队列变量。如果要延迟任务的推送,需要设置delay变量。如果要设置任务的最大重试次数,可以使用tries变量;如果要设置任务可以运行的最大秒数,可以使用超时参数。如果你想手动访问队列,你可以使用trait:IlluminateQueueInteractsWithQueue。任务分发分发服务编写好任务类后,就可以通过调度辅助函数进行分发了。唯一需要传递给调度的参数是这个任务类的一个实例:classPodcastControllerextendsController{publicfunctionstore(Request$request){//创建一个播客...}}如果要延迟执行队列中的任务可以使用任务实例的delay方法。ProcessPodcast::dispatch($podcast)->delay(Carbon::now()->addMinutes(10));通过将任务推送到不同的队列,可以对队列任务进行分类,甚至可以控制分配给不同队列的任务数量。要指定队列,请调用任务实例的onQueue方法:ProcessPodcast::dispatch($podcast)->onQueue('processing');如果使用多个队列连接,则可以将任务推送到指定的连接。指定连接,可以在分发任务时使用onConnection方法:ProcessPodcast::dispatch($podcast)->onConnection('redis');参考资源KingFer
