简单队列系统-RQ深入理解(一)

1,694 阅读3分钟

前言

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的各种数据结构,搭配的十分巧妙,具体案例如下:

  1. 使用set结构存储queue列表和worker列表。
  2. 使用hash结构存储job信息。
  3. 使用zset结构存储finished job。
  4. 使用list结构存储queue下的job,list是RQ的核心。

总结

RQ是一个简单易用的任务队列模块,主要使用了redis来实现异步任务队列,简单易懂,后面继续从源码的角度探究其内部实现,相信一定会有所收获。