基于Redis自动过期的流处理暂停机制

基于Redis自动过期的流处理暂停机制是一种高效、可靠且易于实现的解决方案,防止延时过大的数据影响实时处理自动恢复处理,以避免积压的数据影响实时性,下面就来详细的介绍一下

目录
  • 核心思路
  • 代码实现
    • 1. 初始化Redis连接和键前缀
    • 2. 接收数据时检查暂停状态
    • 3. 检测到延时过大时设置暂停
  • 优势分析
    • 应用场景
      • 扩展优化
        • 总结

          在实时视频流处理系统中,我们有时会遇到某些摄像头的数据延时过大(例如网络问题或处理能力不足),此时我们希望暂时跳过该摄像头的处理,以避免积压的数据影响实时性。本文将介绍一种基于Redis自动过期特性的暂停机制,该机制简单高效,且能自动恢复。

          核心思路

          1. 延时检测:在处理每个摄像头数据时,计算当前时间与数据时间戳的差值
          2. 暂停触发:当延时超过阈值(300秒)时,将该摄像头加入暂停列表
          3. 自动恢复:使用Redis的过期特性,在指定时间后自动恢复处理
          4. 状态共享:通过Redis实现多个进程间的状态共享

          代码实现

          1. 初始化Redis连接和键前缀

          class Tracking_Car:
              def __init__(self, profile_path, logger_) -> None:
                  # ...其他初始化代码...
                  
                  # Redis连接
                  self.redis_db = redis.StrictRedis(
                      host=conf.redis_server.ip,
                      port=conf.redis_server.port,
                      db=conf.redis_server.db,
                      socket_keepalive=True,
                      socket_connect_timeout=10
                  )
                  
                  # 超时存储的Redis key前缀
                  self.TIMEOUT_KEY_PREFIX = "tracking_car:timeout:"
          

          2. 接收数据时检查暂停状态

              def re_stream(self, logger_):
                  pub = self.redis_db.pubsub()
                  pub.subscribe(self.topic)
                  msgs = pub.listen()
                  
                  for msg in msgs:
                      if msg["type"] == "message":
                          json_data = json.loads(msg["data"])
                          ip = json_data["ip"]
                          
                          # 检查是否在暂停列表 - 使用Redis自动过期
                          timeout_key = f"{self.TIMEOUT_KEY_PREFIX}{camera_ip}"
                          if self.redis_db.exists(timeout_key):
                              # 获取剩余时间并记录日志
                              ttl = self.redis_db.ttl(timeout_key)
                              skip_msg = f"跳过{ip }的消息:处于暂停时段({ttl}s剩余)"
                              continue
                          
                          # ...正常处理逻辑...
          

          3. 检测到延时过大时设置暂停

              def write_database(self, cv_list, logger_: MyLogger):
                  # 计算时间差
                  current_time = time.time()
                  _ts = cv_list['timestamp']
                  diff_time = current_time - _ts
                  
                  # 如果时间差超过300秒,使用Redis自动过期设置
                  if diff_time > 300:
                      camera_ip = cv_list["ip"]
                      logger_.warning(f"IP {camera_ip} 延时超过300秒({diff_time:.2f}s),加入暂停列表")
                      
                      # 设置Redis键,自动在300秒后过期
                      timeout_key = f"{self.TIMEOUT_KEY_PREFIX}{camera_ip}"
                      self.redis_db.setex(timeout_key, 300, "1")  # 值可以是任意内容
                      
                      # 删除相关图片并跳过处理
                      self.redis_db.unlink(cv_list["path"])
                      return
                  
                  # ...正常处理逻辑...
          

          优势分析

          1. 自动恢复机制

            • 使用Redis的setex命令设置带过期时间的键
            • 300秒后键自动删除,摄像头自动恢复处理
            • 无需额外的清理任务或状态管理
          2. 进程间状态共享

            • 多个处理进程通过Redis共享暂停状态
            • 新增进程自动获取当前暂停状态
            • 系统扩展性更强
          3. 资源优化

            • 检测到延时过大时立即停止处理
            • 删除相关Redis图片数据,释放内存
            • 避免无效处理消耗CPU资源
          4. 实时监控

            • 记录暂停日志及剩余时间
            • 管理员可实时查看暂停状态

          应用场景

          这种机制特别适用于以下场景:

          1. 网络不稳定的摄像头:某些摄像头可能因网络问题导致数据延迟
          2. 处理能力不足:当系统负载过高时,可暂时跳过部分摄像头
          3. 临时故障处理:摄像头临时故障导致数据积压
          4. 优先级管理:优先处理实时性要求高的摄像头

          扩展优化

          1. 动态阈值设置

            # 根据系统负载动态调整延时阈值
            load = os.getloadavg()[0]
            dynamic_threshold = 300 * (1 + load)  # 负载越高,阈值越大
            
          2. 分级暂停机制

            # 根据延时严重程度设置不同暂停时间
            if diff_time > 600:  # 超过10分钟
                pause_time = 600  # 暂停10分钟
            elif diff_time > 300:  # 超过5分钟
                pause_time = 300  # 暂停5分钟
            
          3. 监控告警

            # 当摄像头被暂停时发送告警
            if diff_time > 300:
                send_alert(f"摄像头 {camera_ip} 因延时过高被暂停")
            

          总结

          基于Redis自动过期的流处理暂停机制是一种高效、可靠且易于实现的解决方案。它通过以下方式提升系统稳定性:

          1. 防止延时过大的数据影响实时处理
          2. 自动恢复处理,减少人工干预
          3. 共享状态,支持分布式部署
          4. 优化资源使用,提升系统整体效率

          这种机制不仅适用于视频流处理系统,也可应用于任何需要根据数据延迟动态调整处理策略的场景。

          到此这篇关于基于Redis自动过期的流处理暂停机制的文章就介绍到这了,更多相关Redis自动过期流处理暂停机制内容请搜索骃骐网以前的文章或继续浏览下面的相关文章希望大家以后多多支持骃骐网!

          您可能感兴趣的文章:

          • 浅谈Redis中的自动过期机制
          • Redis实现订单自动过期功能的示例代码

          相关推荐:

          如何在字典中安全地比较与清理过期日期(如优惠券有效期)

          本文介绍如何在 python 字典中高效、安全地处理日期型值(如优惠券到期日),重点解决字符串日期比较、避免运行时错误及遍历时修改字典等常见问题。 本文介绍如何在 python 字典中高效、安全地处理日期型值(如优惠券到期日),重点解决字符串日期比较、避免运行时错误及遍历时修改字典等常见问题。 在管理优惠券、订阅或任何带有效期的数据时,将日期存储为字符串(如 "2024-04-05")是一种简洁且...

          如何在字典中安全地比较与清理过期日期(如优惠券)

          本文介绍如何在 python 字典中高效、安全地处理日期型值(如优惠券过期日),通过字符串格式化与字典副本遍历,避免运行时错误并准确移除过期项。 本文介绍如何在 python 字典中高效、安全地处理日期型值(如优惠券过期日),通过字符串格式化与字典副本遍历,避免运行时错误并准确移除过期项。 在管理基于日期的键值数据(例如优惠券数据库)时,一个常见需求是:根据当前日期筛选并自动清理已过期的条目。虽然...

          为什么Python 3.11性能提升明显_浅谈Web开发中的特化字节码机制

          Python 3.11比3.10快10%–60%源于运行时字节码特化,对CALL_FUNCTION、BINARY_ADD等高频指令根据实际类型动态生成专用路径,跳过类型检查与查表,需热点预热;Web路由、属性访问、await调用等场景显著受益,但纯I/O操作不受影响。 Python 3.11 的性能提升不是玄学,而是可观察的字节码特化 Python 3.11 比 3.10 快 10%–60%,这背...

          如何在 Python Tkinter 循环中实现命令间的精确暂停

          Tkinter 中不能直接用 time.sleep() 实现界面响应式延时,需改用 root.after() 方法在事件循环中调度任务,才能让窗口逐个延迟创建而不阻塞 GUI。 tkinter 中不能直接用 `time.sleep()` 实现界面响应式延时,需改用 `root.after()` 方法在事件循环中调度任务,才能让窗口逐个延迟创建而不阻塞 gui。 在 Tkinter 应用中,使用 t...

          如何优化Flask应用的启动速度_利用Python的惰性加载与蓝图机制

          Flask应用启动慢的根源在于顶层import重型模块及蓝图中过早初始化。应将pandas、torch等延迟至函数内导入,蓝图只声明路由,初始化逻辑封装为按需调用的函数,并禁用非必要扩展。 为什么Flask应用启动慢?先看真实瓶颈 启动慢不是因为Flask本身重,而是你把 pandas、torch、large_ml_model 这类重型模块全塞进了 app.py 顶层 import —— 它们在应...

          Python Django 5.0如何集成数据库读写分离_配置DATABASES路由机制

          Django 5.0 本身不自动做读写分离,必须靠 DATABASES 多库配置 + 自定义 DatabaseRouter 类 + DATABASE_ROUTERS 注册三者配合,缺一不可;手动用 .using("slave") 是兜底手段,不是集成方案。 直接说结论:Django 5.0 本身不自动做读写分离,必须靠 DATABASES 多库配置 + 自定义 DatabaseRouter 类 +...

          Python 使用 Pika 库怎么开启生产者确认机制(Confirm_delivery)并处理失败?

          channel.confirm_delivery() 必须在声明队列之后调用,因为该方法需 channel 进入“可发布”状态才生效,而声明队列会触发 channel 初始化与状态同步;提前调用则消息不被确认且无报错。 为什么 channel.confirm_delivery() 必须在声明队列之后调用? 因为 RabbitMQ 的确认模式(publisher confirms)是 channel...

          Python爬虫怎么抓取动态更新的API数据_使用轮询机制请求接口

          轮询前需先判断接口是否真需轮询:若API支持增量拉取(如含timestamp参数或last_updated字段)或缓存机制(ETag/If-Modified-Since),应优先采用;否则才考虑轮询,并需封装为可中断、带重试、超时控制与随机抖动的健壮循环。 轮询接口前先确认它是否真需要轮询 很多所谓“动态更新”的数据,其实只是前端用 fetch 或 axios 调了后端 API,而这个 API 本...

          Python中如何实现异步的任务重试机制_利用tenacity库的异步重试装饰器

          tenacity异步重试不能直接用@retry,因默认为同步装饰器,调用time.sleep()会阻塞事件循环;必须显式启用coro=True并确保目标函数为async def。 tenacity异步重试装饰器为什么不能直接用@retry? 因为默认的 @retry 是同步装饰器,它会在协程函数里阻塞事件循环——调用 time.sleep() 而非 asyncio.sleep(),导致整个异步流程...