Laravel - 队列应用及踩过的坑

Laravel 自己实现了队列的机制,如果要看源码解析,这两篇文章写的很好。

本篇要讲的是在应用中遇到的坑。

Laravel 常用的队列驱动

  • Redis
  • beanstalk
  • sqs
  • database

MySQL事务中的队列

队列一般用于比较耗时或不太重要的任务处理,如果不太重要的任务(比如:发邮件、发消息),那就没必要写到事务中,即使写入队列不成功也没什么大不了的。但是如果是比较重要但耗时的任务,为了能快速响应用户,需要用到队列。因为任务比较重要,所以需要保证数据入库写入队列都成功。这种情况下就有一个很重要的点,业务代码需要先入库再写入队列,因为MySQL事务回滚并不会回滚队列。

队列的异常、错误

无论选择哪一种队列驱动,Laravel 都会把错误的任务写入failed_jobs表中(当然,如果你设置了重试次数,那就是重试之后仍然失败后写入)。

  • 当代码异常情况下,如果捕捉就不会写入failed_jobs表中。
  • 当代码错误情况下,就一定会写入(除非mysql写入失败)。

单个任务执行时间

'redis' => [
	'driver' => 'redis',
	'connection' => env('QUEUE_REDIS_CONNECTION', 'default'),
	'queue' => 'default',
	'retry_after' => 60
]

queue.php 文件配置中(以redis 为例),retry_after代表如果单个任务在60秒内没有ack,就会把任务重新放入队列。简单的讲:如果单个任务执行时间超过60秒,就会重复执行。

数据库驱动

如果用 DB 作为驱动,队列定时回去数据库查询需要执行的任务,

select * from `nw_jobs` where `queue` = default and ((`reserved_at` is null and `available_at` <= 1548066079) or (`reserved_at` <= 1548062479)) order by `id` asc limit 1 for update

这条 SQL 会用到主键索引,所以只会锁单条记录。

其他

  • 我们为什么要使用队列,有两个比较重要的原因:异步和重试
  • 由队列就可以联想到消息服务,消息服务就需要满足以下功能
    • 消费者回调
    • 重发机制
    • 消息幂等性

猜你喜欢

转载自blog.csdn.net/melody_lql/article/details/86581654