Skip to content

Commit 8cc1812

Browse files
committed
增加redis驱动下过期任务重发的细节描述
1 parent 46da8c7 commit 8cc1812

File tree

4 files changed

+50
-29
lines changed

4 files changed

+50
-29
lines changed

thinkphp-queue/README.md

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,7 @@ public function failed($jobData){
771771
'attempts' => 2 // 任务的已尝试次数
772772
]
773773
```
774+
redis驱动下,为了实现任务的延迟执行和过期重发,任务将在这三个key中来回转移,详情可见 3.5
774775

775776
- Database
776777

@@ -811,13 +812,33 @@ public function failed($jobData){
811812

812813
![Daemon模式与非daemon模式状态图](https://blog.huzhongyuan.com/wp-content/uploads/2017/02/Daemon%E6%A8%A1%E5%BC%8F%E4%B8%8E%E9%9D%9Edaemon%E6%A8%A1%E5%BC%8F%E7%8A%B6%E6%80%81%E5%9B%BE.svg)
813814

814-
#### 3.4 消息处理的详细流程
815+
#### 3.4 Database模式下消息处理的详细流程
815816

816817
下图中,展示了database 模式下消息处理的详细流程,redis 驱动下大体类似
817818

818819
![Database模式下消息获取和执行的具体流程](https://blog.huzhongyuan.com/wp-content/uploads/2017/02/Database%E9%A9%B1%E5%8A%A8%E4%B8%8B%E6%B6%88%E6%81%AF%E5%A4%84%E7%90%86%E7%9A%84%E5%85%B7%E4%BD%93%E6%B5%81%E7%A8%8B.svg)
819820

820-
#### 3.5 thinkphp-queue的性能
821+
#### 3.5 redis 驱动下的任务重发细节
822+
823+
在redis驱动下,为了实现任务的延迟执行和过期重发,任务将在这三个key中来回转移。
824+
825+
在3.4 Database模式下消息处理的消息流程中,我们知道,如果配置的expire 不是null ,那么 thinkphp-queue的work进程每次在获取下一个可执行任务之前,会先尝试重发所有过期的任务。而在redis驱动下,这个步骤则做了更多的事情,详情如下:
826+
827+
1.`queue:xxx:delayed` 的key中查询出有哪些任务在当前时刻已经可以开始执行,然后将这些任务转移到 `queue:xxx` 的key的尾部。
828+
2.`queue:xxx:reserved` 的key中查询出有哪些任务在当前时刻已经过期,然后将这些任务转移到 `queue:xxx`的key的尾部。
829+
3. 尝试从 `queue:xxx` 的key的头部取出一个任务,如果取出成功,那么,将这个任务转移到 `queue:xxx:reserved` 的key 的头部,同时将这个任务实例化成任务对象,交给消费者去执行。
830+
831+
用图来表示这个步骤的具体过程如下:
832+
833+
redis队列中的过期任务重发步骤--执行前:
834+
835+
![redis队列中的过期任务重发步骤-执行前](https://blog.huzhongyuan.com/wp-content/uploads/2017/02/redis%E9%98%9F%E5%88%97%E4%B8%AD%E7%9A%84%E4%BB%BB%E5%8A%A1%E7%AE%A1%E7%90%86-1.png)
836+
837+
redis队列中的过期任务重发步骤--执行后:
838+
839+
![redis队列中的过期任务重发步骤--执行后](https://blog.huzhongyuan.com/wp-content/uploads/2017/02/redis%E9%98%9F%E5%88%97%E4%B8%AD%E7%9A%84%E4%BB%BB%E5%8A%A1%E7%AE%A1%E7%90%86-2.png)
840+
841+
#### 3.6 thinkphp-queue的性能
821842

822843
- 测试环境 :
823844

@@ -836,9 +857,9 @@ public function failed($jobData){
836857

837858
**注意:**由于在测试时,Host 机本身的cpu和内存长期100%,并且虚拟机中的各项服务并未专门调优,因此该测试结果**并不具备参考性**
838859

839-
#### 3.6 thinkphp-queue 的N种错误使用姿势
860+
#### 3.7 thinkphp-queue 的N种错误使用姿势
840861

841-
- **3.6.1** 在 消费者类的 `fire()` 方法中,忘记使用 `$job->delete()` 去删除消息,这种情况下,会产生一系列的bug:
862+
- **3.7.1** 在 消费者类的 `fire()` 方法中,忘记使用 `$job->delete()` 去删除消息,这种情况下,会产生一系列的bug:
842863

843864
- 配置的 expire 为 `null` , 则该任务被执行一次后会永远留在消息队列中,占用消息队列的空间 , 除非开发者另行处理。
844865

@@ -861,17 +882,17 @@ public function failed($jobData){
861882
- 编写失败回调事件,将事件中失败的任务及时通知给开发人员。
862883

863884

864-
- **3.6.2** 使用了 `queue:work --daemon` ,但更新代码后没有使用 `queue:restart` 重启 work 进程, 使得 work 进程中的代码与最新的代码不同,出现各种问题。
885+
- **3.7.2** 使用了 `queue:work --daemon` ,但更新代码后没有使用 `queue:restart` 重启 work 进程, 使得 work 进程中的代码与最新的代码不同,出现各种问题。
865886

866-
- **3.6.3** 使用了 `queue:work --daemon` ,但是消费者类的 fire() 方法中存在死循环,或 `sleep(n)` 等逻辑,导致消息队列被堵塞;或者使用了 `exit()` , `die()` 这样的逻辑,导致work进程直接终止 。
887+
- **3.7.3** 使用了 `queue:work --daemon` ,但是消费者类的 fire() 方法中存在死循环,或 `sleep(n)` 等逻辑,导致消息队列被堵塞;或者使用了 `exit()` , `die()` 这样的逻辑,导致work进程直接终止 。
867888

868-
- **3.6.4** 配置的 expire 为 `null` ,这时如果采用的是 Redis 驱动且使用了延迟功能,如 `later(n)``release(n)` 方法或者 `--delay` 参数不为0 , 那么将导致被延迟的任务永远无法处理。(这个可能属于框架的[Bug](https://github.com/top-think/think-queue/issues/12))
889+
- **3.7.4** 配置的 expire 为 `null` ,这时如果采用的是 Redis 驱动且使用了延迟功能,如 `later(n)``release(n)` 方法或者 `--delay` 参数不为0 , 那么将导致被延迟的任务永远无法处理。(这个可能属于框架的[Bug](https://github.com/top-think/think-queue/issues/12))
869890

870-
- **3.6.5** 配置的 expire 为`null` ,但并没有自行处理过期的任务,导致过期的任务得不到处理,且一直占用消息队列的空间。
891+
- **3.7.5** 配置的 expire 为`null` ,但并没有自行处理过期的任务,导致过期的任务得不到处理,且一直占用消息队列的空间。
871892

872-
- **3.6.6** 配置的 expire `不为null` ,但配置的 expire 时间太短,以至于 expire 时间 < 消费者的 `fire()` 方法所需时间 + 删除该任务所需的时间 ,那么任务将被误认为执行超时,从而被消息队列还原为待执行状态。
893+
- **3.7.6** 配置的 expire `不为null` ,但配置的 expire 时间太短,以至于 expire 时间 < 消费者的 `fire()` 方法所需时间 + 删除该任务所需的时间 ,那么任务将被误认为执行超时,从而被消息队列还原为待执行状态。
873894

874-
- **3.6.7** 使用 `Queue::push($jobHandlerClassName , $jobData, $jobQueueName );` 推送任务时,`$jobData` 中包含未序列化的对象。这时,在消费者端拿到的 `$jobData ` 中拿到的是该对象的public 属性的键值对数组。因此,需要在推送前手动序列化对象,在消费者端再手动反序列化还原为对象。
895+
- **3.7.7** 使用 `Queue::push($jobHandlerClassName , $jobData, $jobQueueName );` 推送任务时,`$jobData` 中包含未序列化的对象。这时,在消费者端拿到的 `$jobData ` 中拿到的是该对象的public 属性的键值对数组。因此,需要在推送前手动序列化对象,在消费者端再手动反序列化还原为对象。
875896

876897

877898
### 四 拓展
@@ -898,22 +919,22 @@ public function failed($jobData){
898919

899920
TP5的消息队列与Laravel的消息队列比较相似,下面是与laravel 中的消息队列的一些对比:
900921

901-
| | TP5 | LARAVEL |
902-
| --------- | ---------------------------------- | --------------------------------------- |
903-
| 内置的驱动 | Database,Redis,Sync,TopThink | Database,Redis, Sync(在laravel中称为 null)。 |
904-
| Redis驱动要求 | 安装redis的C扩展 | 安装 predis 包 |
905-
| 推送任务 | 允许推送 消费者类名,消费者对象 | 允许推送消费者类名,消费者对象,闭包 |
906-
| 失败任务处理 | 触发失败回调事件 (有Bug) | 触发失败回调事件 + 移动任务到 failed_jobs表? |
907-
| 消息订阅 | subscribe 命令(未实现/未提供) + Topthink驱动 | subscribe 命令 + IronMQ 驱动 |
908-
| 删除任务 | 消费者类中手动删除 | 任务完成后自动删除 |
909-
| 推送到多个队列 | 需自己实现 | 原生支持 |
910-
| 延迟执行 | 支持 (有Bug) | 支持 |
911-
| 消息重发 | 支持 | 支持 |
912-
| 检查已执行次数 | 原生支持 | 需在消费者类中显式 use 相关的 trait |
913-
| 执行方式 | work 模式 + listen 模式 | work 模式 + listen 模式 |
914-
| 进程命令 | 开启,停止,重启 | 开启,停止,重启 |
915-
| 任务命令 || 展示失败任务列表,重试某个失败任务,删除某个失败任务 |
916-
| 支持的事件 | 失败回调事件 | 失败回调事件,支持消费前事件,消费后事件 |
922+
| | thinkphp-queue (v1.1.2) | laravel-queue (v5.3) |
923+
| --------- | ----------------------------------- | --------------------------------------- |
924+
| 内置的驱动 | Database,Redis,Sync,TopThink | Database,Redis, Sync(在laravel中称为 null)。 |
925+
| Redis驱动要求 | 安装redis的C扩展 | 安装 predis 包 + LUA脚本 |
926+
| 推送任务 | 允许推送 消费者类名,消费者对象 | 允许推送消费者类名,消费者对象,闭包 |
927+
| 失败任务处理 | 触发失败回调事件 (有Bug) | 触发失败回调事件 + 移动任务到 failed_jobs表? |
928+
| 消息订阅 | subscribe 命令+ Topthink驱动(注:未实现/未提供) | subscribe 命令 + 安装IronMQ 驱动 |
929+
| 删除任务 | 消费者类中手动删除 | 任务完成后自动删除 |
930+
| 推送到多个队列 | 需自己实现 | 原生支持 |
931+
| 延迟执行 | 支持 (有Bug) | 支持 |
932+
| 消息重发 | 支持 | 支持 |
933+
| 检查已执行次数 | 原生支持 | 需在消费者类中显式 use 相关的 trait |
934+
| 执行方式 | work 模式 + listen 模式 | work 模式 + listen 模式 |
935+
| 进程命令 | 开启,停止,重启 | 开启,停止,重启 |
936+
| 任务命令 | | 展示失败任务列表,重试某个失败任务,删除某个失败任务 |
937+
| 支持的事件 | 失败回调事件 | 失败回调事件,支持消费前事件,消费后事件 |
917938

918939
### 五 待讨论的问题
919940

thinkphp-queue/ThinkPHP5中的队列.html

Lines changed: 3 additions & 3 deletions
Large diffs are not rendered by default.
32.8 KB
Loading
38.2 KB
Loading

0 commit comments

Comments
 (0)