定时器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. MarkDown学习总结-2020.05.11

    1.使用工具 1.1Typora 官网地址:https://www.typora.io/ 下载链接 2.基础入门 注意: []中的内容则是对应格式的标记符,默认全部标识符后面需要多加一个空格才能生效. ...

  2. SRX_Test_2_sound

    声音(sound) [问题描述] 雅礼中学的校门口在修建地铁,而由此带来的噪音问题让周边的居民困扰不已.环保局正在研究 一项评估模型,可以定量评价噪音的危害程度.这项评估模型是这样的:将每一条街道视作 ...

  3. 基于Kubernetes和OpenKruise的可变基础设施实践

    本文首发在OPPO互联网公众号,欢迎点击转载 https://mp.weixin.qq.com/s/hRvZz_bZfchmP0tkF6M2OA 对于可变基础设施的思考 kubernetes中的可变与 ...

  4. C语言是如何诞生的?地位怎样?未来发展趋势?

      C语言的历史 C语言的原型是A语言(ALGOL 60语言). 1963年,剑桥大学将ALGOL 60语言发展成为CPL(Combined Programming Language)语言. 1967 ...

  5. linq 查询的结果会开辟新的内存吗?

    一:背景 1. 讲故事 昨天群里有位朋友问:linq 查询的结果会开辟新的内存吗?如果开了,那是对原序列集里面元素的深拷贝还是仅仅拷贝其引用? 其实这个问题我觉得问的挺好,很多初学 C# 的朋友或多或 ...

  6. Spring Boot 2.4发布了,但Spring Cloud用户不推荐着急升级

    前段时间Spring Boot发布了本年度最后一个重要更新版本:Spring Boot 2.4.0. 最近在社群里也开始有讨论关于Spring Boot 2.4的一些使用问题.我发现有很多Spring ...

  7. DRF的ModelSerializer的使用

    在views中添加 from django.shortcuts import render # Create your views here. from rest_framework.views im ...

  8. Python 表达式 i += x 与 i = i + x 等价吗?

    Python 表达式 i += x 与 i = i + x 等价吗? 看个例子 a = [1, 2, 3] b = a # 写法一 b += [4] # 写法二 # b = b + [4] print ...

  9. sqli-labs less-24(二次注入)

    less-24 原理: 在网站处理用户提交的数据的时候,只是将某些敏感字符进行了转义.因而使得用户第一次提交的时候不会被当做代码执行.但是这些数据存入数据库的时候却没有转义,而网站程序默认数据库中的数 ...

  10. MySQL增强半同步的搭建实验,和一些参数的个人理解

    关于参数理解,已补充实验,可以查看: rpl_semi_sync_master_wait_no_slave 参数研究实验 环境信息 role ip port hostname master 192.1 ...