Redis限流器疑问:万级并发请求下是否会丢失9999次请求?
Redis 基于列表的限流器疑问解答
背景与问题
Redis官方文档给出的基于列表实现的限流器代码如下:
FUNCTION LIMIT_API_CALL(ip) current = LLEN(ip) IF current > 10 THEN ERROR "too many requests per second" ELSE IF EXISTS(ip) == FALSE MULTI RPUSH(ip,ip) EXPIRE(ip,1) EXEC ELSE RPUSHX(ip,ip) END PERFORM_API_CALL() END
官方提到该实现存在竞态条件,但仅会在极少数情况下丢失一次API调用,限流仍能正常工作。现咨询:若同时发送10000次请求,是否会丢失9999次请求?该限流器是否仍可正常运行?
解答
1. 不会丢失9999次请求
首先要明确:那些被限流拦截(返回too many requests per second)的请求不属于“丢失”,这是限流器正常工作的结果——本来就应该拦截超过阈值的请求。
官方提到的“丢失一次API调用”是极端场景下的小概率事件:仅当目标键刚过期,多个请求同时检测到键不存在时,可能出现某一个请求执行了PERFORM_API_CALL(),但因为事务执行的时序问题,没有成功将记录写入列表(或者过期时间被重复设置),但这种情况只会发生1次左右,绝不可能出现9999次丢失。
2. 限流器仍可正常运行
即使同时涌入10000次请求,这个限流器的核心逻辑依然有效:
- 绝大多数请求会在第一步
LLEN(ip)时检测到列表长度超过10,被直接拦截,不会触发API调用; - 只有前10个左右的请求能通过初始判断,进入后续流程;
- 竞态条件只会导致极个别请求绕过长度限制(比如瞬间出现11次API调用),或者极个别请求的列表记录未被写入,但整体的限流效果依然符合预期——每秒的API调用次数会被控制在10次上下,不会出现大规模超限的情况。
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

