定时器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

通过环形队列实现高效任务触发的设计说明

  1. redis集合【slot】
  • 以redis多个有规律的键名的有序集合组成环形数组
key_1
key_2
....
key_n
  • 有序集合

命令

ZADD key score member
有序集合中包含两部分, 一个是score, 一个是member

score作为剩余循环次数
meber作为事件ID
  1. python多进程
  • 计算当前时间应该处理的卡槽

    当前slot索引 = (当前时间 % 卡槽总数 + 当前时间戳 % 卡槽总数) % 卡槽总数

"%"为取余数操作

  • 创建独立子进程处理

    当前子进程需要快速读取的剩余循环次数为0事件ID

    删除当前slot已取出的事件ID

    开始把事件ID依次转交给事件handler处理

应用说明

  1. 启动定时器
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()
  1. 添加需要延时触发事件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实现环形队列高效定时器的更多相关文章

  1. Atitit.提升软件稳定性---基于数据库实现的持久化 循环队列 环形队列

    Atitit.提升软件稳定性---基于数据库实现的持久化  循环队列 环形队列 1. 前言::选型(马) 1 2. 实现java.util.queue接口 1 3. 当前指针的2个实现方式 1 1.1 ...

  2. python之消息队列

    引言 你是否遇到过两个(多个)系统间需要通过定时任务来同步某些数据?你是否在为异构系统的不同进程间相互调用.通讯的问题而苦恼.挣扎?如果是,那么恭喜你,消息服务让你可以很轻松地解决这些问题.消息服务擅 ...

  3. <2014 05 16> 线性表、栈与队列——一个环形队列的C语言实现

    栈与队列都是具有特殊存取方式的线性表,栈属于先进后出(FILO),而队列则是先进先出(FIFO).栈能够将递归问题转化为非递归问题,这是它的一个重要特性.除了FILO.FIFO这样的最普遍存取方式外, ...

  4. 高性能环形队列框架 Disruptor 核心概念

    高性能环形队列框架 Disruptor Disruptor 是英国外汇交易公司LMAX开发的一款高吞吐低延迟内存队列框架,其充分考虑了底层CPU等运行模式来进行数据结构设计 (mechanical s ...

  5. DPDK 无锁环形队列(Ring)详解

    DPDK 无锁环形队列(Ring) 此篇文章主要用来学习和记录DPDK中无锁环形队列相关内容,结合了官方文档说明和源码中的实现,供大家交流和学习. Author : Toney Email : vip ...

  6. 【Machine Learning】决策树案例:基于python的商品购买能力预测系统

    决策树在商品购买能力预测案例中的算法实现 作者:白宁超 2016年12月24日22:05:42 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本 ...

  7. 【转】C#环形队列

    概述 看了一个数据结构的教程,是用C++写的,可自己C#还是一个菜鸟,更别说C++了,但还是大胆尝试用C#将其中的环形队列的实现写出来,先上代码: 1 public class MyQueue< ...

  8. HQueue:基于HBase的消息队列

    HQueue:基于HBase的消息队列   凌柏   ​1. HQueue简介 HQueue是一淘搜索网页抓取离线系统团队基于HBase开发的一套分布式.持久化消息队列.它利用HTable存储消息数据 ...

  9. 基于 Python 和 Scikit-Learn 的机器学习介绍

    Reference:http://mp.weixin.qq.com/s?src=3&timestamp=1474985436&ver=1&signature=at24GKibw ...

随机推荐

  1. 「CSP-S 2020」动物园

    description luogu loj(暂无数据) solution 这道题作为T2,对选手们考试开始后先通看一遍所有题目的好习惯,以及判断究竟谁才是真正的签到题的重要能力进行了较好的锻炼, 特别 ...

  2. Flink-1-状态化流处理概述

    第1章 状态化流处理概述 参考书籍 Stream Processing with Apache Flinkhttps://www.oreilly.com/library/view/stream-pro ...

  3. PHP 递归删除目录中文件

    /** * 递归删除目录中文件 * @param $pathname * @return bool */public static function delDir($pathname)//要删除的目录 ...

  4. P5851 [USACO19DEC]Greedy Pie Eaters P

    如果只考虑选哪些奶牛吃派和奶牛吃派的顺序,就会陷入僵局,那么我们可以考虑派的情况. 套路地令 \(f_{i,j}\) 表示 \(i\sim j\) 这一段派,能满足一些奶牛,它们的最大可能体重. \[ ...

  5. 2019年第十届蓝桥杯【C++省赛B组】D、E、G、H、I题解

    这场有几道题目思路,在之前比赛中遇到过 D. 数的分解 #枚举 题意 将\(2019\)分解成\(3\)个各不相同的正整数之和,并且每个正整数都不包含数字\(2\)和\(4\),一共有多少种分解方法? ...

  6. linux下安装python3.7.1

    一.安装依赖环境 输入命令:yum -y install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readlin ...

  7. centOs7.5.64以上版本的操作系统搭建GitLab记录

    一. 安装并配置必要的依赖关系在CentOS系统上安装所需的依赖:ssh,防火墙,postfix(用于邮件通知) ,wget,以下这些命令也会打开系统防火墙中的HTTP和SSH端口访问. 1.安装ss ...

  8. 自动化运维工具之Puppet变量、正则表达式、流程控制、类和模板

    前文我们了解了puppet的file.exec.cron.notify这四种核心资源类型的使用以及资源见定义通知/订阅关系,回顾请参考https://www.cnblogs.com/qiuhom-18 ...

  9. (九)ELF和动态链接

    前言: 我们都知道我们所写的程序是被编译为一条条的CPU指令去执行的,但是在linux系统下能够运行的程序在windows环境下却运行不起来,但是我们使用的CPU明明是一样的,这又是为什么呢? 一.程 ...

  10. PyQt(Python+Qt)学习随笔:Qt Designer中主窗口对象unifiedTitleAndToolBarOnMac属性

    unifiedTitleAndToolBarOnMac 用于确认在mac操作系统上是否使用统一的标题和工具栏外观 有如下几个限制: 1.不支持使用带OpenGl内容的窗口,包括QGLWidget 和 ...