基于Python实现环形队列高效定时器
定时器Python实现代码
import time
import redis
import multiprocessing class Base: """
redis配置
"""
redis_conf = {} """
环形队列使用redis进行存储
"""
_ri = None """
定时器轮盘大小
"""
slot_num = 15 """
存储环形队列使用的redis缓存key
"""
cache_key = 'wheel:slot_' def __init__(self, **kwargs):
for k in kwargs:
if hasattr(self, k):
setattr(self, k, kwargs[k]) self._ri = redis.Redis(**self.redis_conf) class Timer(Base):
"""
当前slot的下标
"""
_current = 0 """
事件处理
"""
event_handler = None def worker(self):
"""
# TODO 测试每个卡槽有1W事件ID的处理效率
独立进程,分发事件id给事件处理器
:return:
"""
key = self.cache_key + str(self._current) # 获取当前卡槽中需要触发的事件ID
event_ids = self._ri.zrangebyscore(key, 0, 0) # 删除当前卡槽中需要触发的事件ID
self._ri.zremrangebyscore(key, 0, 0) # 把当前卡槽剩下的事件ID全部遍历出来,减少一次剩余循环次数
surplus_event_ids = self._ri.zrange(key, 0, -1) for mid in surplus_event_ids:
self._ri.zincrby(key, mid, -1) # 把事件ID转交给handler处理
for mid in event_ids:
self.event_handler(eid=mid) exit(0) def run(self):
"""
启动进程
:return:
"""
while True:
p = multiprocessing.Process(target=self.worker)
p.start() time.sleep(1) self._current = int(time.time()) % self.slot_num class TimerEvent(Base): def add(self, event_id, emit_time):
"""
添加事件ID到定时器
:param event_id: 事件ID
:param emit_time: 触发时间
:return:
"""
current_time = int(time.time())
diff = emit_time - current_time if diff > 0:
# 计算循环次数
cycle = int(diff / self.slot_num)
# 计算要存入的slot的索引
index = (diff % self.slot_num + current_time % self.slot_num) % self.slot_num res = self._ri.zadd(self.cache_key + str(index), str(event_id), cycle)
return True if res else False return False # TODO 批量添加同一时间,不同事件ID # TODO 批量添加不同时间,不同事件ID
通过环形队列实现高效任务触发的设计说明
- redis集合【slot】
- 以redis多个有规律的键名的有序集合组成环形数组
key_1
key_2
....
key_n
- 有序集合
命令
ZADD key score member
有序集合中包含两部分, 一个是score, 一个是member score作为剩余循环次数
meber作为事件ID
- python多进程
计算当前时间应该处理的卡槽
当前slot索引 = (当前时间 % 卡槽总数 + 当前时间戳 % 卡槽总数) % 卡槽总数
"%"为取余数操作
创建独立子进程处理
当前子进程需要快速读取的剩余循环次数为0事件ID
删除当前slot已取出的事件ID
开始把事件ID依次转交给事件handler处理
应用说明
- 启动定时器
import Timer
import time def event_handler(eid):
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())), eid) t = Timer(redis_conf={
'host': '127.0.0.1',
'port': 6379,
'password': '123456',
'db': 0
}, event_handler=event_handler) times = int(time.time()) print('Current Time is ' + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(times))) t.run()
- 添加需要延时触发事件ID
import TimerEvent
import time te = TimerEvent(redis_conf={
'host': '127.0.0.1',
'port': 6379,
'password': '123456',
'db': 0
}) times = int(time.time()) print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(times))) after_seconds_alert = 20 for x in range(100):
te.add(x, times + after_seconds_alert + x) print('Firs Emit will happened at ' + time.strftime(
'Start:%Y-%m-%d %H:%M:%S',
time.localtime(times + after_seconds_alert))
)
本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理
想要获取更多Python学习资料可以加
QQ:2955637827私聊
或加Q群630390733
大家一起来学习讨论吧!
基于Python实现环形队列高效定时器的更多相关文章
- Atitit.提升软件稳定性---基于数据库实现的持久化 循环队列 环形队列
Atitit.提升软件稳定性---基于数据库实现的持久化 循环队列 环形队列 1. 前言::选型(马) 1 2. 实现java.util.queue接口 1 3. 当前指针的2个实现方式 1 1.1 ...
- python之消息队列
引言 你是否遇到过两个(多个)系统间需要通过定时任务来同步某些数据?你是否在为异构系统的不同进程间相互调用.通讯的问题而苦恼.挣扎?如果是,那么恭喜你,消息服务让你可以很轻松地解决这些问题.消息服务擅 ...
- <2014 05 16> 线性表、栈与队列——一个环形队列的C语言实现
栈与队列都是具有特殊存取方式的线性表,栈属于先进后出(FILO),而队列则是先进先出(FIFO).栈能够将递归问题转化为非递归问题,这是它的一个重要特性.除了FILO.FIFO这样的最普遍存取方式外, ...
- 高性能环形队列框架 Disruptor 核心概念
高性能环形队列框架 Disruptor Disruptor 是英国外汇交易公司LMAX开发的一款高吞吐低延迟内存队列框架,其充分考虑了底层CPU等运行模式来进行数据结构设计 (mechanical s ...
- DPDK 无锁环形队列(Ring)详解
DPDK 无锁环形队列(Ring) 此篇文章主要用来学习和记录DPDK中无锁环形队列相关内容,结合了官方文档说明和源码中的实现,供大家交流和学习. Author : Toney Email : vip ...
- 【Machine Learning】决策树案例:基于python的商品购买能力预测系统
决策树在商品购买能力预测案例中的算法实现 作者:白宁超 2016年12月24日22:05:42 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本 ...
- 【转】C#环形队列
概述 看了一个数据结构的教程,是用C++写的,可自己C#还是一个菜鸟,更别说C++了,但还是大胆尝试用C#将其中的环形队列的实现写出来,先上代码: 1 public class MyQueue< ...
- HQueue:基于HBase的消息队列
HQueue:基于HBase的消息队列 凌柏 1. HQueue简介 HQueue是一淘搜索网页抓取离线系统团队基于HBase开发的一套分布式.持久化消息队列.它利用HTable存储消息数据 ...
- 基于 Python 和 Scikit-Learn 的机器学习介绍
Reference:http://mp.weixin.qq.com/s?src=3×tamp=1474985436&ver=1&signature=at24GKibw ...
随机推荐
- Python基础整理,懒得分类了,大家对付看看吧
第一次搞这么多图
- 【模板】【P1182】数列分段II——二分答案
题意:给定一列数,分成m段,使每段和的最大值最小. 考虑二分最小段和size,答案显然满足单调性.可以在每次check中累加数列元素判断当前组的总和是否在size以内.由于序列元素均为非负整数,前缀和 ...
- 干货分享:盘点那些最常用的Linux命令,需熟记!
- dubbo起停之服务暴露
由上一节可知带上dubbo@Service注解的对象,在注册成为bean之后会进一步注册一个ServiceBean,服务暴露便是在这里 public void afterPropertiesSet() ...
- B. Irreducible Anagrams【CF 1290B】
思路: 设tx为t类别字符的个数. ①对于长度小于2的t明显是"YES"②对于字符类别只有1个的t明显是"YES"③对于字符类别有2个的t,如左上图:如果str ...
- js预解析练习
分析下面两段代码 console.log(num)//undefined var num = 10 f()//可以执行 //f2()不可以执行 console.log(f)//function con ...
- moviepy音视频剪辑:使用fl_time报错OSError: MoviePy error: failed to read the first frame of video file
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt+moviepy音视频剪辑实战 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 在m ...
- Python运算符的优先级是怎样的?
优先级数字越高表示优先级越高,有关运算符的详细介绍请参考<Python运算符大全>
- PyQt(Python+Qt)学习随笔:Qt Designer中的menu菜单及menu bar菜单栏
菜单由menu bar菜单栏和menu菜单两部分构成,分别对应类QMenuBar和QMenu. menuBar是包含一系列下拉菜单项组成,menu包含两种,一种是直接对应Action的,一种是父菜单, ...
- PyQt(Python+Qt)学习随笔:实现toolButton与Action的关联
在Qt Designer中,如果创建的窗口为主窗口QMainWindow类型,可以通过<PyQt(Python+Qt)学习随笔:Qt Designer中怎么给toolBar添加按钮 >介绍 ...