Python使用Redis实现作业调度系统(超简单)


Posted in Python onMarch 22, 2016

概述

Redis是一个开源,先进的key-value存储,并用于构建高性能,可扩展的Web应用程序的完美解决方案。

Redis从它的许多竞争继承来的三个主要特点:

Redis数据库完全在内存中,使用磁盘仅用于持久性。

相比许多键值数据存储,Redis拥有一套较为丰富的数据类型。

Redis可以将数据复制到任意数量的从服务器。

Redis 优势

异常快速:Redis的速度非常快,每秒能执行约11万集合,每秒约81000+条记录。

支持丰富的数据类型:Redis支持最大多数开发人员已经知道像列表,集合,有序集合,散列数据类型。这使得它非常容易解决各种各样的问题,因为我们知道哪些问题是可以处理通过它的数据类型更好。

操作都是原子性:所有Redis操作是原子的,这保证了如果两个客户端同时访问的Redis服务器将获得更新后的值。

多功能实用工具:Redis是一个多实用的工具,可以在多个用例如缓存,消息,队列使用(Redis原生支持发布/订阅),任何短暂的数据,应用程序,如Web应用程序会话,网页命中计数等。

步入主题:

Redis作为内存数据库的一个典型代表,已经在很多应用场景中被使用,这里仅就Redis的pub/sub功能来说说怎样通过此功能来实现一个简单的作业调度系统。这里只是想展现一个简单的想法,所以还是有很多需要考虑的东西没有包括在这个例子中,比如错误处理,持久化等。

下面是实现上的想法

MyMaster:集群的master节点程序,负责产生作业,派发作业和获取执行结果。

MySlave:集群的计算节点程序,每个计算节点一个,负责获取作业并运行,并将结果发送会master节点。

channel CHANNEL_DISPATCH:每个slave节点订阅一个channel,比如“CHANNEL_DISPATCH_[idx或机器名]”,master会向此channel中publish被dispatch的作业。

channel CHANNEL_RESULT:用来保存作业结果的channel,master和slave共享此channel,master订阅此channel来获取作业运行结果,每个slave负责将作业执行结果发布到此channel中。

Master代码

#!/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 = 'CHANNEL_DISPATCH'
CHANNEL_RESULT = 'CHANNEL_RESULT'
class MyMaster():
def __init__(self):
pass
def start(self):
MyServerResultHandleThread().start()
MyServerDispatchThread().start()
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, 100):
channel = CHANNEL_DISPATCH + '_' + str(random.randint(1, 3))
print("Dispatch job %s to %s" % (str(i), channel))
ret = r.publish(channel, str(i))
if ret == 0:
print("Dispatch job %s failed." % str(i))
time.sleep(5)
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("Received finished job %s" % message['data'])
if __name__ == "__main__":
MyMaster().start()
time.sleep(10000)

说明

MyMaster类 - master主程序,用来启动dispatch和resulthandler的线程

MyServerDispatchThread类 - 派发作业线程,产生作业并派发到计算节点

MyServerResultHandleThread类 - 作业运行结果处理线程,从channel里获取作业结果并显示

Slave代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from datetime import datetime
import time
import threading
import random
import redis
REDIS_HOST = 'localhost'
REDIS_PORT = 6379
REDIS_DB = 0
CHANNEL_DISPATCH = 'CHANNEL_DISPATCH'
CHANNEL_RESULT = 'CHANNEL_RESULT'
class MySlave():
def __init__(self):
pass
def start(self):
for i in range(1, 4):
MyJobWorkerThread(CHANNEL_DISPATCH + '_' + str(i)).start()
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)
for message in p.listen():
if message['type'] != 'message':
continue
print("%s: Received dispatched job %s " % (self.channel, message['data']))
print("%s: Run dispatched job %s " % (self.channel, message['data']))
time.sleep(2)
print("%s: Send finished job %s " % (self.channel, message['data']))
ret = r.publish(CHANNEL_RESULT, message['data'])
if ret == 0:
print("%s: Send finished job %s failed." % (self.channel, message['data']))
if __name__ == "__main__":
MySlave().start()
time.sleep(10000)

说明

MySlave类 - slave节点主程序,用来启动MyJobWorkerThread的线程

MyJobWorkerThread类 - 从channel里获取派发的作业并将运行结果发送回master

测试

首先运行MySlave来定义派发作业channel。

然后运行MyMaster派发作业并显示执行结果。

有关Python使用Redis实现作业调度系统(超简单),小编就给大家介绍这么多,希望对大家有所帮助!

Python 相关文章推荐
gearman的安装启动及python API使用实例
Jul 08 Python
Python标准库内置函数complex介绍
Nov 25 Python
Python 高级专用类方法的实例详解
Sep 11 Python
Python数据类型中的“冒号“[::]——分片与步长操作示例
Jan 24 Python
python3实现SMTP发送邮件详细教程
Jun 19 Python
Python判断一个文件夹内哪些文件是图片的实例
Dec 07 Python
python之当你发现QTimer不能用时的解决方法
Jun 21 Python
python 将日期戳(五位数时间)转换为标准时间
Jul 11 Python
python实现键盘输入的实操方法
Jul 16 Python
Django框架 信号调度原理解析
Sep 04 Python
python对Excel的读取的示例代码
Feb 14 Python
python 使用tkinter与messagebox写界面和弹窗
Mar 20 Python
python编写简单爬虫资料汇总
Mar 22 #Python
使用Nginx+uWsgi实现Python的Django框架站点动静分离
Mar 21 #Python
Python中的条件判断语句与循环语句用法小结
Mar 21 #Python
举例讲解Python中的迭代器、生成器与列表解析用法
Mar 20 #Python
深入解析Python中函数的参数与作用域
Mar 20 #Python
总结Python编程中函数的使用要点
Mar 20 #Python
两个命令把 Vim 打造成 Python IDE的方法
Mar 20 #Python
You might like
php过滤html中的其他网站链接的方法(域名白名单功能)
2014/04/24 PHP
PHP访问Google Search API的方法
2015/03/05 PHP
使弱类型的语言JavaScript变强势
2009/06/22 Javascript
Javascript/Jquery——简单定时器的多种实现方法
2013/07/03 Javascript
Jquery右下角抖动、浮动 实例代码(兼容ie6、FF)
2013/08/15 Javascript
通过JS来动态的修改url,实现对url的增删查改
2014/09/01 Javascript
node.js中的console.timeEnd方法使用说明
2014/12/09 Javascript
Jquery实现弹性滑块滑动选择数值插件
2015/08/08 Javascript
浅谈Nodejs观察者模式
2015/10/13 NodeJs
js实现延时加载Flash的方法
2015/11/26 Javascript
AngularJs Injecting Services Into Controllers详解
2016/09/02 Javascript
React Native中NavigatorIOS组件的简单使用详解
2018/01/27 Javascript
Canvas实现微信红包照片效果
2018/08/21 Javascript
vue动画效果实现方法示例
2019/03/18 Javascript
浅谈Javascript中的对象和继承
2019/04/19 Javascript
解决vue中el-tab-pane切换的问题
2020/07/19 Javascript
python条件和循环的使用方法
2013/11/01 Python
使用Python的web.py框架实现类似Django的ORM查询的教程
2015/05/02 Python
python3+PyQt5使用数据库窗口视图
2018/04/24 Python
python日期时间转为字符串或者格式化输出的实例
2018/05/29 Python
python3爬虫学习之数据存储txt的案例详解
2019/04/24 Python
在python中将list分段并保存为array类型的方法
2019/07/15 Python
Python通过递归获取目录下指定文件代码实例
2019/11/07 Python
python实现简单猜单词游戏
2020/12/24 Python
CSS 说明横向进度条最后显示文字的实现代码
2020/11/10 HTML / CSS
HTML5表格_动力节点Java学院整理
2017/07/11 HTML / CSS
详解HTML5 Canvas绘制不规则图形时的非零环绕原则
2016/03/21 HTML / CSS
沪江旗下的海量优质课程平台:沪江网校
2017/11/07 全球购物
adidas瑞典官方网站:购买阿迪达斯鞋子和运动服
2019/12/11 全球购物
房屋租赁协议书
2014/04/10 职场文书
气象学专业个人求职信
2014/04/22 职场文书
北京奥运会口号
2014/06/21 职场文书
Python Pandas pandas.read_sql_query函数实例用法分析
2021/06/21 Python
SpringBoot2零基础到精通之异常处理与web原生组件注入
2022/03/22 Java/Android
Java界面编程实现界面跳转
2022/06/16 Java/Android
使用CSS实现百叶窗效果示例代码
2023/05/07 HTML / CSS