前言
RQ (Redis Queue)是一个简单的Python库,用于对任务进行排队,并使用worker在后台处理它们。它得到了Redis的支持,并且被设计成具有较低的进入门槛。除了RQ外,比较流行的任务系统就是celery,后者就复杂很多了。
快速入门
从一个简单案例入手,结合跟踪redis信息来分析RQ内部原理。
## task.py
def add(x,y):
return x,y
## main.py
from redis import Redis
from rq import Queue
from task import *
q = Queue(connection=Redis())
q.enqueue(add,2,3)
- 加入任务到队列中 python main.py
- 启动rq worker rq worker,如下是rq支持的命令,包含启动worker、获取info信息、重入队失败任务、清空某个队列、挂起worker和恢复worker。
Commands:
empty Empty given queues.
info RQ command-line monitor.
requeue Requeue failed jobs.
resume Resumes processing of queues, that were suspended with `rq...
suspend Suspends all workers, to resume run `rq resume`
worker Starts an RQ worker.
跟踪任务
- 入队任务后
127.0.0.1:6379> keys *
1) "rq:queue:default" # list结构
2) "rq:queues" # set结构
3) "rq:job:867275fc-72df-4775-b351-a8ad6592f65c" # hash结构
127.0.0.1:6379> hgetall rq:job:867275fc-72df-4775-b351-a8ad6592f65c
1) "status"
2) "queued"
3) "created_at"
4) "2021-04-09T16:26:19.832422Z"
5) "data"
6) "x\x9ck`\x9d*\xc1\x00\x01\x1a=\x1c%\x89\xc5\xd9z\x89))S\xfc\xbc\x99\xbc\x99\xdb\xa6\xd4N)\x99\xa2\a\x00\x8e\xe8\t\xd7"
7) "started_at"
8) ""
9) "ended_at"
10) ""
11) "last_heartbeat"
12) ""
13) "worker_name"
14) ""
15) "origin"
16) "default"
17) "description"
18) "task.add(2, 3)"
19) "enqueued_at"
20) "2021-04-09T16:26:19.832590Z"
21) "timeout"
22) "180"
- 执行任务后
127.0.0.1:6379> keys *
1) "rq:finished:default" ## zset结构,执行成功的job集
2) "rq:job:867275fc-72df-4775-b351-a8ad6592f65c"
3) "rq:workers" ## set结构
4) "rq:queues"
5) "rq:workers:default" ## set结构,关联某个队列
6) "rq:worker:acb1fa840f774e6a95461d7812e56c68" ## 其中一个worker,重启进程会产生新的
7) "rq:clean_registries:default"
127.0.0.1:6379> hgetall rq:job:867275fc-72df-4775-b351-a8ad6592f65c
1) "status"
2) "finished" ## 状态变化
3) "created_at"
4) "2021-04-09T16:26:19.832422Z"
5) "data"
6) "x\x9ck`\x9d*\xc1\x00\x01\x1a=\x1c%\x89\xc5\xd9z\x89))S\xfc\xbc\x99\xbc\x99\xdb\xa6\xd4N)\x99\xa2\a\x00\x8e\xe8\t\xd7"
7) "started_at"
8) "2021-04-09T16:29:32.630894Z"
9) "ended_at"
10) "2021-04-09T16:29:32.646619Z"
11) "last_heartbeat"
12) "2021-04-09T16:29:32.629091Z"
13) "worker_name"
14) ""
15) "origin"
16) "default"
17) "description"
18) "task.add(2, 3)"
19) "enqueued_at"
20) "2021-04-09T16:26:19.832590Z"
21) "timeout"
22) "180"
23) "result"
24) "\x80\x05\x95\a\x00\x00\x00\x00\x00\x00\x00K\x02K\x03\x86\x94."
可以看到任务队列系统RQ的数据存储依赖了redis的各种数据结构,搭配的十分巧妙,具体案例如下:
- 使用set结构存储queue列表和worker列表。
- 使用hash结构存储job信息。
- 使用zset结构存储finished job。
- 使用list结构存储queue下的job,list是RQ的核心。
总结
RQ是一个简单易用的任务队列模块,主要使用了redis来实现异步任务队列,简单易懂,后面继续从源码的角度探究其内部实现,相信一定会有所收获。