基於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實現環形佇列高效定時器Python佇列定時器
- 使用陣列實現環形佇列Scala版本陣列佇列
- 陣列模擬佇列 以及佇列的複用(環形佇列)陣列佇列
- C語言之環形佇列C語言佇列
- Python佇列的三種佇列實現方法Python佇列
- 基於 Redis 的方式實現非同步佇列Redis非同步佇列
- 資料結構與演算法——佇列(環形佇列)資料結構演算法佇列
- C#通過rabbitmq實現定時任務(延時佇列)C#MQ佇列
- 佇列 優先順序佇列 python 程式碼實現佇列Python
- Python實現堆疊與佇列Python佇列
- 使用 RabbitMQ 實現延時佇列MQ佇列
- 基於訊息佇列(RabbitMQ)實現延遲任務佇列MQ
- 基於迴圈佇列的BFS的原理及實現佇列
- Procrastinate:基於PostgreSQL的Python任務佇列ASTSQLPython佇列
- 基於Redis的簡易延時佇列Redis佇列
- 基於redis實現定時任務Redis
- 一個Java基於阻塞的定時消費記憶體佇列Java記憶體佇列
- .NET 高效能緩衝佇列實現 BufferQueue佇列
- Python實現執行緒安全佇列Python執行緒佇列
- python基於opencv 實現影像時鐘PythonOpenCV
- 使用db-scheduler實現高效能持久佇列佇列
- js定時任務佇列JS佇列
- 陣列模擬佇列進階版本——環形佇列(真正意義上的排隊)陣列佇列
- Node.js結合RabbitMQ延遲佇列實現定時任務Node.jsMQ佇列
- netty系列之:HashedWheelTimer一種定時器的高效實現Netty定時器
- 通過佇列實現棧OR通過棧實現佇列佇列
- Python 通過List 實現佇列的操作Python佇列
- Python實現環形連結串列詳解Python
- PHP基於Redis訊息佇列實現的訊息推送的方法PHPRedis佇列
- 百行程式碼實現基於Redis的可靠延遲佇列行程Redis佇列
- 佇列的一種實現:迴圈佇列佇列
- 資料結構-迴圈佇列(Python實現)資料結構佇列Python
- RabbitMQ使用 prefetch_count優化佇列的消費,使用死信佇列和延遲佇列實現訊息的定時重試,golang版本MQ優化佇列Golang
- 基於asyncio和redis的Python分散式任務佇列RedisPython分散式佇列
- 看圖理解基於陣列的佇列陣列佇列
- 9. 題目:對佇列實現棧&用棧實現佇列佇列
- 秒殺最佳化-基於阻塞佇列實現秒殺最佳化佇列
- 用佇列實現棧佇列