Redis限流策略分享,确保系统流量稳定可控

文章导读
使用Redis实现限流的核心是通过原子操作如INCR和EXPIRE来计数和设置过期时间。基本代码示例:public boolean limit(String key, int limit, int expireSeconds) { String countKey = "limit:" + key; String count = redisTemplate.opsForValue().increme
📋 目录
  1. 固定窗口计数器限流
  2. 漏桶算法限流
  3. 令牌桶算法限流
  4. Redis+Lua脚本平滑限流
  5. 分布式限流方案
  6. 基于Redis的热点key限流
A A

使用Redis实现限流的核心是通过原子操作如INCR和EXPIRE来计数和设置过期时间。基本代码示例:public boolean limit(String key, int limit, int expireSeconds) { String countKey = "limit:" + key; String count = redisTemplate.opsForValue().increment(countKey); if (Integer.parseInt(count) == 1) { redisTemplate.expire(countKey, expireSeconds, TimeUnit.SECONDS); } return Integer.parseInt(count) > limit; }

固定窗口计数器限流

固定窗口计数器是一种简单粗暴的限流方式,每个窗口周期内(比如1s)请求次数达到阈值后拒绝后续请求。Redis原子操作INCR配合EXPIRE实现,代码示例:String key = "rate_limit:" + userId + ":" + timeWindow; Long count = redis.incr(key); if(count == 1){ redis.expire(key, windowSize); } if(count > maxCount){ //拒绝请求 }

漏桶算法限流

漏桶算法的核心是水桶有固定容量,水流以恒定速率流出,无论流入速率多快都会平滑输出。Redis实现:维护当前水位leaky_bucket:current,请求到来时如果当前水位<桶容量则接受并增加水位,同时定时任务以恒定速率减少水位。代码:if(redis.get(current) < capacity){ redis.incrby(current,1); //接受请求 }else{ //拒绝 }

Redis限流策略分享,确保系统流量稳定可控

令牌桶算法限流

令牌桶算法允许突发流量,桶中令牌以恒定速率产生,请求需要消耗令牌。Redis+zset实现,每个时间窗口产生tokens数量的score,后续请求从zset中移除最小score的元素作为tokenId,多余请求则拒绝。多线程安全,用Lua脚本保证原子性。

Redis+Lua脚本平滑限流

使用Lua脚本保证原子性,避免并发问题。示例Lua脚本:local key = KEYS[1] local limit = tonumber(ARGV[1]) local expire = tonumber(ARGV[2]) local current = redis.call('INCR',key) if current == 1 then redis.call('EXPIRE',key,expire) end if current > limit then redis.call('DEL',key) return 0 end return 1

分布式限流方案

在分布式环境下,使用Redis集群或Codis,确保key分布均匀避免热点key。结合Nginx upstream进行多层限流,应用层Redis限流配合网关层漏桶,实现流量稳定可控。对于秒杀场景,预热令牌桶并结合库存扣减双重保障。

Redis限流策略分享,确保系统流量稳定可控

基于Redis的热点key限流

热点参数限流:将热点key放入集合,每分钟采样top N参数作为热点,新增请求先判断是否命中热点key,有则走特殊限流逻辑。采样命令:sorted_set.zrevrangebyscore('hot_params', '+inf', 0, 'WITHSCORES', LIMIT N)

FAQ
Q: Redis限流为什么比内存计数器好?
A: 支持分布式多实例共享状态,避免单点故障。
Q: 固定窗口和滑动窗口有什么区别?
A: 固定窗口边界对齐时间点有流量突刺,滑动窗口更平滑但实现复杂。
Q: 如何处理Redis故障时的限流降级?
A: 客户端fallback到内存计数器或直接放行保守策略。
Q: 限流key设计原则?
A: 包含业务+用户/接口+时间窗口,避免key爆炸。