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 相关文章推荐
Python实现简单拆分PDF文件的方法
Jul 30 Python
Python下载指定页面上图片的方法
May 12 Python
tensorflow建立一个简单的神经网络的方法
Feb 10 Python
Python实现定时备份mysql数据库并把备份数据库邮件发送
Mar 08 Python
使用APScheduler3.0.1 实现定时任务的方法
Jul 22 Python
Django model 中设置联合约束和联合索引的方法
Aug 06 Python
python与pycharm有何区别
Jul 01 Python
python 实现两个npy档案合并
Jul 01 Python
Pandas DataFrame求差集的示例代码
Dec 13 Python
快速一键生成Python爬虫请求头
Mar 04 Python
Python Pandas常用函数方法总结
Jun 15 Python
python自动化测试之Selenium详解
Mar 13 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学习之简单计算器实现代码
2011/06/09 PHP
Yii+MYSQL锁表防止并发情况下重复数据的方法
2016/07/14 PHP
php使用curl获取header检测开启GZip压缩的方法
2018/08/15 PHP
用函数式编程技术编写优美的 JavaScript
2006/11/25 Javascript
jquery下为Event handler传递动态参数的代码
2011/01/06 Javascript
基于jquery打造的百分比动态色彩条插件
2012/09/19 Javascript
js中如何把字符串转化为对象、数组示例代码
2013/07/17 Javascript
JS格式化数字保留两位小数点示例代码
2013/10/15 Javascript
jQuery实现鼠标可拖动调整表格列宽度
2014/05/26 Javascript
chrome下jq width()方法取值为0的解决方法
2014/05/26 Javascript
jQuery队列操作方法实例
2014/06/11 Javascript
用jquery模仿的a的title属性的例子
2014/10/22 Javascript
浅谈JavaScript函数节流
2014/12/09 Javascript
jQuery 回调函数(callback)的使用和基础
2015/02/26 Javascript
Nodejs express框架一个工程中同时使用ejs模版和jade模版
2015/12/28 NodeJs
微信小程序 location API实例详解
2016/10/02 Javascript
利用JS实现点击按钮后图片自动切换的简单方法
2016/10/24 Javascript
微信小程序开发经验总结(推荐)
2017/01/11 Javascript
js使用highlight.js高亮你的代码
2017/08/18 Javascript
JQuery通过键盘控制键盘按下与松开触发事件
2020/08/07 jQuery
Python的高级Git库 Gittle
2014/09/22 Python
Python注释详解
2016/06/01 Python
python学生信息管理系统(初级版)
2018/10/17 Python
python模拟菜刀反弹shell绕过限制【推荐】
2019/06/25 Python
Python 画出来六维图
2019/07/26 Python
Python进度条的制作代码实例
2019/08/31 Python
HTML5高仿微信聊天、微信聊天表情|对话框|编辑器功能
2018/04/23 HTML / CSS
英国最大的户外商店:Go Outdoors
2019/04/17 全球购物
Conforama西班牙:您的家具、装饰和电器商店
2020/02/21 全球购物
电气专业推荐信范文
2013/11/18 职场文书
公司新员工的演讲稿注意事项
2014/01/01 职场文书
人事专员岗位职责范本
2014/03/04 职场文书
2014年质检工作总结
2014/11/26 职场文书
感恩教师节主题班会
2015/08/12 职场文书
SQL实现LeetCode(177.第N高薪水)
2021/08/04 MySQL
SQL Server中搜索特定的对象
2022/05/25 SQL Server