Python结合Redis Pub/Sub实现轻量级作业调度系统

苏见山
苏见山
发布时间:2026-10-12| 3人浏览过
原创

本文介绍如何利用Python与Redis的发布订阅(Pub/Sub)机制构建一个轻量级的作业调度系统。通过Master节点负责作业派发与结果汇总,Slave节点按频道接收并执行任务,配合多线程实现异步通信。文章提供完整代码、运行顺序及注意事项,适用于需要简易消息分发与结果收集的开发场景。

系统原理与架构

基于Redis内存特性与丰富的数据类型,利用其原生支持的消息发布/订阅(Pub/Sub)功能,可以搭建一个低延迟的轻量级作业调度框架。系统分为主控节点(Master)与工作节点(Slave):Master负责生成任务ID并向指定频道发布调度指令,同时订阅结果频道收集反馈;Slave监听对应分发频道,执行模拟任务后将执行状态回传至共享的结果频道。该模式无需外部消息中间件,适合本地测试或微服务间的简单异步通信。

环境准备

确保已安装Python 3.x,并通过 pip install redis 安装依赖库。本地需运行一个标准的Redis服务(默认地址 localhost:6379)。脚本中将直接使用 redis.StrictRedis 连接实例,无需额外配置集群,单节点即可满足本示例的跑通需求。

第1步:编写主控节点(Master)代码

目的:初始化调度逻辑,启动任务派发线程与结果处理线程。入口处直接实例化 MyMaster 类并调用 start()。
动作参数:设定Redis连接参数,定义派发频道前缀 CHANNEL_DISPATCH 与结果频道 CHANNEL_RESULT。Master会随机挑选编号为1~3的计算节点频道发送作业ID,并在后台持续监听结果频道打印完成信息。
代码实现(已修正原始缩进以确保语法正确):

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
import threading
import random
import redis

REDIS_HOST = 'localhost'
REDIS_PORT = 6379
REDIS_DB = 0
CHANNEL_DISPATCH_PREFIX = 'CHANNEL_DISPATCH'
CHANNEL_RESULT = 'CHANNEL_RESULT'

class MyServerDispatchThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        r = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT, db=REDIS_DB)
        for i in range(1, 11):
            channel = f"{CHANNEL_DISPATCH_PREFIX}_{random.randint(1, 3)}"
            print(f"Dispatch job {i} to {channel}")
            ret = r.publish(channel, str(i))
            if ret == 0:
                print(f"Dispatch job {i} failed.")
            time.sleep(1)

class MyServerResultHandleThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        r = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT, db=REDIS_DB)
        p = r.pubsub()
        p.subscribe(CHANNEL_RESULT)
        for message in p.listen():
            if message['type'] != 'message':
                continue
            print(f"Received finished job {message['data']}")

class MyMaster():
    def start(self):
        MyServerResultHandleThread().start()
        MyServerDispatchThread().start()

if __name__ == "__main__":
    MyMaster().start()
    time.sleep(10000)

第2步:编写工作节点(Slave)代码

目的:让计算节点按需监听特定分发频道,执行任务后回写结果。入口为 MySlave.start(),默认创建3个Worker线程分别监听 CHANNEL_DISPATCH_1 到 _3。
动作参数:每个线程独立维护PubSub连接,收到消息后模拟2秒计算耗时,随即通过 r.publish(CHANNEL_RESULT, ...) 将作业号发回结果频道。
代码实现:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
import threading
import redis

REDIS_HOST = 'localhost'
REDIS_PORT = 6379
REDIS_DB = 0
CHANNEL_DISPATCH_PREFIX = 'CHANNEL_DISPATCH'
CHANNEL_RESULT = 'CHANNEL_RESULT'

class MyJobWorkerThread(threading.Thread):
    def __init__(self, channel):
        threading.Thread.__init__(self)
        self.channel = channel

    def run(self):
        r = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT, db=REDIS_DB)
        p = r.pubsub()
        p.subscribe(self.channel)
        print(f"{self.channel}: Worker started.")
        for message in p.listen():
            if message['type'] != 'message':
                continue
            job_id = message['data']
            print(f"{self.channel}: Received dispatched job {job_id}")
            print(f"{self.channel}: Running dispatched job {job_id}")
            time.sleep(2)
            print(f"{self.channel}: Send finished job {job_id}")
            ret = r.publish(CHANNEL_RESULT, job_id)
            if ret == 0:
                print(f"{self.channel}: Result publish failed.")

class MySlave():
    def start(self):
        for i in range(1, 4):
            MyJobWorkerThread(f"{CHANNEL_DISPATCH_PREFIX}_{i}").start()

if __name__ == "__main__":
    MySlave().start()
    time.sleep(10000)

第3步:测试运行与完成判断

操作顺序如下:
1. 打开终端,运行Slave程序:
python slave.py
Slave启动后会创建3个工作线程并阻塞在 p.listen() 等待分发频道推送消息。
2. 另开一个终端,运行Master程序:
python master.py
Master会每隔1秒向随机选中的频道发布作业ID。Slave接收到后会打印执行日志,并将结果回传到 CHANNEL_RESULT。Master的结果处理线程捕获该消息后,会在控制台输出“Received finished job...”。

完成状态判断:当Master控制台稳定交替显示派发消息与结果接收记录,且无频繁断连或阻塞报错时,即表示调度通道已打通。注意,由于使用了纯内存Pub/Sub,若节点重启或连接断开,未消费的消息将丢失,生产环境需结合Redis Stream或持久化队列补充可靠性保障。

简要总结

本文通过Python标准库多线程与Redis原生发布订阅接口,快速搭建了一套可运行的轻量级作业调度原型。核心在于正确区分分发频道(用于任务投递)与结果频道(用于状态回传),并利用 publish() 的返回值辅助监控投递状态。以上就是利用Python和Redis Pub/Sub实现轻量级作业调度系统的详细内容,更多关于Python高级应用与分布式消息通信的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。