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中的集合类型操作符
Aug 19 Python
python 自动化将markdown文件转成html文件的方法
Sep 23 Python
Django 路由系统URLconf的使用
Oct 11 Python
使用python批量化音乐文件格式转换的实例
Jan 09 Python
Python初学者常见错误详解
Jul 02 Python
python修改字典键(key)的方法
Aug 05 Python
基于Python+Appium实现京东双十一自动领金币功能
Oct 31 Python
如何分离django中的媒体、静态文件和网页
Nov 12 Python
通过实例解析python描述符原理作用
Jan 22 Python
pandas数据处理之绘图的实现
Jun 15 Python
selenium学习教程之定位以及切换frame(iframe)
Jan 04 Python
Python+Appium实现自动抢微信红包
May 21 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 array_filter除去数组中的空字符元素
2020/06/21 PHP
php set_time_limit()函数的使用详解
2013/06/05 PHP
php中用socket模拟http中post或者get提交数据的示例代码
2013/08/08 PHP
php实现随机生成易于记忆的密码
2015/06/19 PHP
php设计模式之委托模式
2016/02/13 PHP
PHP 中使用ajax时一些常见错误总结整理
2017/02/27 PHP
laravel 解决多库下的DB::transaction()事务失效问题
2019/10/21 PHP
Yii框架 session 数据库存储操作方法示例
2019/11/18 PHP
EasyUI中实现form表单提交的示例分享
2015/03/01 Javascript
javascript显示上周、上个月日期的处理方法
2016/02/03 Javascript
js仿QQ中对联系人向左滑动、滑出删除按钮的操作
2016/04/07 Javascript
Angular.js自定义指令学习笔记实例
2017/02/24 Javascript
详解vue-admin和后端(flask)分离结合的例子
2018/02/12 Javascript
Vue包大小优化的实现(从1.72M到94K)
2021/02/18 Vue.js
[42:56]VGJ.S vs Serenity 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
python实现查询苹果手机维修进度
2015/03/16 Python
深入讲解Python中的迭代器和生成器
2015/10/26 Python
python的scikit-learn将特征转成one-hot特征的方法
2018/07/10 Python
Python实现全排列的打印
2018/08/18 Python
对python中url参数编码与解码的实例详解
2019/07/25 Python
python随机模块random使用方法详解
2020/02/14 Python
Python3.8安装Pygame教程步骤详解
2020/08/14 Python
CSS3 优势以及网页设计师如何使用CSS3技术
2009/07/29 HTML / CSS
CSS3中的transform属性进行2D和3D变换的基本用法
2016/05/12 HTML / CSS
前端面试必备之html5的新特性
2017/09/05 HTML / CSS
马来西亚最大的在线隐形眼镜商店:MrLens
2019/03/27 全球购物
.net工程师笔试题
2012/06/09 面试题
销售人员中英文自荐信
2013/09/22 职场文书
工作违纪检讨书
2014/02/17 职场文书
高中军训感言600字
2014/03/11 职场文书
秋天的雨教学反思
2014/04/27 职场文书
学生会竞选演讲稿怎么写
2014/08/26 职场文书
给老婆的道歉信
2015/01/20 职场文书
驳回起诉裁定书
2015/05/19 职场文书
事业单位工作人员2015年度思想工作总结
2015/10/15 职场文书
Win11绿屏怎么办?Win11绿屏死机的解决方法
2021/11/21 数码科技