You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redis中如何订阅指定频道的订阅者数量(避免轮询)

解决方案

要解决Redis中实时获取频道订阅者数量的问题——因为原生PUBSUB NUMSUB只能主动查询无法订阅变化,轮询又会浪费资源——你可以通过以下几种方案实现:

1. 客户端主动上报订阅/退订事件(最直接的实时方案)

Redis本身不会在客户端订阅/退订时触发通知,所以需要在业务层的订阅逻辑里额外添加两步原子操作,同时推送订阅数更新:

  • 当客户端订阅目标频道(比如chat:room1)时:

    # 原子增加订阅计数器
    INCR chat:room1:subcount
    # 获取最新订阅数并推送到专门的更新频道
    PUBLISH chat:room1:subcount_updated $(GET chat:room1:subcount)
    
  • 当客户端主动退订时:

    # 原子减少订阅计数器
    DECR chat:room1:subcount
    # 推送更新后的订阅数
    PUBLISH chat:room1:subcount_updated $(GET chat:room1:subcount)
    

需要监控订阅数的服务,直接订阅chat:room1:subcount_updated频道,就能实时收到订阅数变化,完全无需轮询。

异常断开的处理

如果客户端意外断开(比如网络中断),Redis不会自动触发退订的计数器减操作,这时候需要做存活校验:

  • 客户端订阅后,定期(比如每25秒)向Redis发送SET client:sub:{用户ID} chat:room1 EX 30,用过期时间标记存活状态
  • 后台启动定时任务(比如每分钟一次),用SCAN遍历所有client:sub:*的键,找出已过期的条目,对对应频道执行DECR操作后推送更新。

2. 利用Redis键空间通知(Keyspace Notifications)

如果不想在客户端逻辑里加太多代码,可以通过Redis的键空间通知监听订阅计数器的变化:

  1. 先修改Redis配置,开启键空间通知:

    # 开启所有键的事件通知(K=键空间事件,E=键事件,A=所有事件)
    CONFIG SET notify-keyspace-events KEA
    
  2. 维护一个订阅计数器键(比如chat:room1:subcount),客户端订阅/退订时仍需执行INCR/DECR更新这个键

  3. 监控服务订阅对应键的变化事件:

    # 订阅db 0中chat:room1:subcount键的所有变化事件
    SUBSCRIBE __keyspace@0__:chat:room1:subcount
    
  4. 当计数器变化时,监控服务会收到事件通知,此时再执行GET chat:room1:subcount获取最新订阅数。

优缺点

  • 优点:不需要修改太多客户端逻辑,依赖Redis原生通知机制
  • 缺点:通知仅告知键发生变化,不会直接返回新值,需额外查询;键空间通知会产生一定额外流量,需根据实际场景评估性能。

3. 基于Redis Hash的在线客户端管理

如果需要更精准的在线用户统计,可以用Hash存储每个订阅频道的在线客户端:

  • 客户端订阅时:

    # 将用户ID加入频道的在线Hash,值设为当前时间戳
    HSET chat:room1:online_users user123 $(date +%s)
    # 同时更新计数器并推送
    INCR chat:room1:subcount
    PUBLISH chat:room1:subcount_updated $(GET chat:room1:subcount)
    
  • 客户端定时刷新存活状态:

    HSET chat:room1:online_users user123 $(date +%s)
    
  • 后台定时清理超时用户:

    # 获取所有在线用户的时间戳
    HGETALL chat:room1:online_users
    # 遍历筛选出超时(比如超过30秒)的用户,逐个删除
    HDEL chat:room1:online_users userXXX
    # 重新计算订阅数并推送
    SET chat:room1:subcount $(HLEN chat:room1:online_users)
    PUBLISH chat:room1:subcount_updated $(GET chat:room1:subcount)
    

这种方法能更准确统计在线用户,尤其是需要区分用户是否真的在线的场景,但需要维护定时清理逻辑。


内容的提问来源于stack exchange,提问作者tobiasBora

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 00:00:02