怎样在Redis中限制单个客户端订阅频道的最大数量_修改源码或通过代理层过滤

夜丽小哥_3753

夜丽小哥_3753

2026-06-25

940人浏览

原创

redis未提供单客户端订阅频道数限制功能,需在代理层或客户端sdk中实现;源码无校验逻辑,硬编码修改风险高;maxclients与maxmemory无法间接解决该问题。

怎样在redis中限制单个客户端订阅频道的最大数量_修改源码或通过代理层过滤

Redis 本身不提供“单个客户端订阅频道数量上限”的原生配置项,maxclients 控制的是总连接数,不是每个连接能订多少频道。想限制单个客户端的 subscribe 频道数,必须在外部做——要么改 Redis 源码(不推荐),要么在代理层或客户端 SDK 层拦截过滤。

Redis 源码里根本没有单客户端频道数校验逻辑

翻过 redis/src/pubsub.c(截至 7.2 和 8.0 版本),subscribeCommand 函数只做三件事:解析参数、往 client->pubsub_channels 字典里插入频道、更新频道的订阅者链表。它不会检查当前 client 已经订了多少个频道,也不会读任何 per-client 的 limit 配置。

这意味着:

  • 你改 redis.conf 加一行 max-subscribe-per-client 10 是完全无效的,Redis 启动时会直接忽略
  • 即使硬编码加校验(比如在 subscribeCommand 开头加 if (dictSize(c->pubsub_channels) >= 10) {...}),也得重新编译、上线、维护私有分支——线上稳定性风险陡增
  • Redis 官方明确表示该机制设计为“无硬限”,靠运维和客户端自律控制规模

用代理层(如 Redis Proxy)拦截并计数 subscribe 请求

这是生产环境最可行的方案。主流开源 proxy 如 twemproxy、redis-shake、predixy 不支持 pub/sub 流量,但 redis-cell 或自研 L4/L7 代理可以做到。关键点是:在 proxy 解析 Redis 协议时识别 subscribe 和 psubscribe 命令,并对每个 client socket 维护一个频道计数器。

实操建议:

  • 用 SOCKS5 或 TLS SNI 提取 client IP + port,作为唯一标识(避免多个连接伪装成同一 client)
  • 对每条 subscribe channel1 channel2 channel3 命令,拆出频道名列表,累加到该 client 的计数器;超过阈值(如 50)则返回 -ERR too many subscriptions 并断开连接
  • 注意 unsubscribe 和 punsubscribe 必须同步减计数,否则内存泄漏
  • 不要依赖 client 发送的 CLIENT SETNAME,它可被任意伪造

在客户端 SDK 层强制做订阅前校验

如果你能统一管控所有业务代码(比如全部用 Python + redis-py),比改服务端更轻量、更可控。核心是在调用 pubsub.subscribe() 前插入一道检查。

Redis Skill - 高性能缓存管理
Redis Skill - 高性能缓存管理

Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。

下载

示例(Python):

class LimitedPubSub:
    def __init__(self, redis_client, max_channels=20):
        self.redis = redis_client
        self.pubsub = redis_client.pubsub()
        self.max_channels = max_channels
        self._subscribed = set()

    def subscribe(self, *channels):
        if len(self._subscribed) + len(channels) > self.max_channels:
            raise ValueError(f"Exceeds max {self.max_channels} subscribed channels")
        self._subscribed.update(channels)
        return self.pubsub.subscribe(*channels)

    def unsubscribe(self, *channels):
        self._subscribed -= set(channels)
        return self.pubsub.unsubscribe(*channels)

这个方式的问题在于:它只管自己这一个 SDK 实例,无法跨进程/跨语言生效;而且如果业务绕过封装直连 redis-cli 或其他 client,就完全失效。

为什么别碰 maxclients 或 maxmemory 来“曲线救国”

有人试图通过压低 maxclients 间接限制总订阅数,或者靠 maxmemory 触发淘汰来“逼退”高频订阅者——这属于误用。

原因很实在:

  • maxclients 是 TCP 连接总数,一个 client 订 1 个频道和订 1000 个频道,都只占 1 个连接
  • maxmemory 影响的是键空间,pub/sub 频道元数据不计入内存统计(它们存在 server.pubsub_channels 字典里,不走 LRU)
  • 真正吃资源的是消息广播时的 CPU 和网卡带宽,不是订阅动作本身;限制错地方,问题照旧

真正要防的,从来不是“能订多少个频道”,而是“某个 client 是否在疯狂 subscribe/unsubscribe 扰乱事件循环”,或者“是否用通配符 psubscribe news.* 匹配了上千个实际不存在的频道”。这些行为得靠 proxy 或 client 端的请求频控+模式白名单来拦,不是靠数量上限。

相关专题

更多
常用的数据库软件
常用的数据库软件

常用的数据库软件有MySQL、Oracle、SQL Server、PostgreSQL、MongoDB、Redis、Cassandra、Hadoop、Spark和Amazon DynamoDB。更多关于数据库软件的内容详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.02

4289

19

内存数据库有哪些
内存数据库有哪些

内存数据库有Redis、Memcached、Apache Ignite、VoltDB、TimesTen、H2 Database、Aerospike、Oracle TimesTen In-Memory Database、SAP HANA和ache Cassandra。更多关于内存数据库相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.14

3795

11

mongodb和redis哪个读取速度快
mongodb和redis哪个读取速度快

redis 的读取速度比 mongodb 更快。原因包括:1. redis 使用简单的键值存储,而 mongodb 存储 json 格式的数据,需要解析和反序列化。2. redis 使用哈希表快速查找数据,而 mongodb 使用 b-tree 索引。因此,redis 在需要高性能读取操作的应用程序中是一个更好的选择。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.02

6852

6

redis怎么做缓存服务器
redis怎么做缓存服务器

redis 作为缓存服务器的答案:redis 是一款开源、高性能、分布式的键值存储,可作为缓存服务器使用。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

623

6

redis怎么解决数据一致性
redis怎么解决数据一致性

redis 提供了两种一致性模型,以维护副本数据一致性:强一致性 (sync) 确保写操作仅在复制到所有从节点后才完成;最终一致性 (async) 则在主节点上写操作后认为已完成,牺牲一致性换取性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

736

6

mysql和redis怎么保证双写一致性
mysql和redis怎么保证双写一致性

确保 mysql 和 redis 双写一致性的技术包括:1、事务性更新:同时更新 mysql 和 redis,保证一致性;2、主从复制:mysql 主服务器更改同步到 redis 从服务器;3、基于事件的更新:mysql 记录更改并发送到 redis等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

6462

6

redis缓存一般存些什么数据
redis缓存一般存些什么数据

redis缓存中存储的数据类型包括:字符串、哈希、列表、集合、有序集合、位图、地理空间数据和hyperloglog。这些数据类型适用于存储各种数据,从简单信息到复杂对象和地理位置。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

1140

6

redis的8种数据类型有哪些
redis的8种数据类型有哪些

redis 提供 8 种数据类型:字符串(文本、数字、二进制)、哈希(键值对)、列表(有序集合)、集合(无序唯一元素)、有序集合(按分数排序)、地理空间(地理位置)、hyperloglog(估计大数据基数)和位图(位序列存储)。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

1016

6

redis主要作用有哪些
redis主要作用有哪些

redis 的主要作用包括:1. 缓存数据,提高访问速度;2. 充当消息队列,实现消息传递;3. 存储各种数据类型,如字符串、散列和集合;4. 管理会话信息,确保可靠性和可用性;5. 限制请求速率,防止服务器超载等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.04.07

5758

6

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
phpEnv手册
phpEnv手册

共0课时 | 0人学习

进程与SOCKET
进程与SOCKET

共6课时 | 0.5万人学习