基于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 ...
随机推荐
- # 夏普R shv39 0基础精简优化指南
手机介绍 夏普AQUOS R是目前市面上用户数量和好评数量都非常多的一款产品.它性价比极高,适合各个年龄段的用户选择来满足办公或者家用或者娱乐等不同方面的需求.目前闲鱼价格在400左右,搭载骁龙835 ...
- 【ACwing 96】奇怪的汉诺塔——区间dp
(题面来自ACwing) 汉诺塔问题,条件如下: 1.这里有A.B.C和D四座塔. 2.这里有n个圆盘,n的数量是恒定的. 3.每个圆盘的尺寸都不相同. 4.所有的圆盘在开始时都堆叠在塔A上,且圆盘尺 ...
- Codeforces Round #670 (Div. 2) D. Three Sequences 题解(差分+思维+构造)
题目链接 题目大意 给你一个长为n的数组a,要你构造一个非严格单调上升的数组b和一个非严格单调下降的数组c,使得\(b_i+c_i=a_i\) 要你使这两个数组b,c中最大的元素最小,还有q次修改(q ...
- Java基础教程——Date类和Calendar类
Date类和Calendar类都是关于日期的类,都在java.util包中,使用时需要import. Date java.util.Date类的对象用来表示时间和日期,用得最多的是获取系统当前日期和时 ...
- Django中ModelForm详解
1.ModelForm组件介绍:这个组件的功能就是把model和form组合起来 2.ModelForm的使用 1.首先需要导入ModelForm from django.forms import M ...
- 第4.6节 print、import及断言
一.print函数 前面第二章介绍了print的语法,其语法如下: print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ...
- SQL注入WAF绕过姿势
(1)大小写绕过 此类绕过不经常使用,但是用的时候也不能忘了它,他原理是基于SQL语句不分大小写的,但过滤只过滤其中一种. 这里有道题 (2)替换关键字 这种情况下大小写转化无法绕过而且正则表达式会替 ...
- python中的Restful
哇,昨天组里进行总结的时候,小哥哥和小姐姐真是把我给秀到了,跟他们一比,我总结的太垃圾了,嘤嘤嘤.因为我平常不怎么总结,总结的话,有word还有纸质的,现在偏向于纸质,因为可以练练字.个人观点是,掌握 ...
- 对flask的学习
任务需求:一个登录,注册页面 任务环境:pycharm 2018 专业版,python3.7,win 10专业版 ------------------------------------------- ...
- C#中SQL SERVER 2008字符数据类型使用心得
一.尽可能使用Varchar,少使用或者不使用Char字符类型 因为char类型输入的数据长度达不到设计长度,会用空格补足,下面是数据表设计图: 下面是编辑前200行的图: 凡是输入的数据长度达不到设 ...