使用Redis实现分布式限流

599 阅读1分钟

需求

  1. 分布式限流
  2. 限制队列长度,同一时间内只能支持一定用户的使用
  3. 限制用户在队列内的时间和操作次数,超过时间或次数即退出队列重新排队
  4. 支持队列动态配置

设计

数据结构

image-20201006161510343使用一个zset来模拟一个用户队列,其中score的值表示用户入队时的时间戳(图中只是为了表示方便,实际为时间戳)

通过zremrangebyscore命令可以很方便地将过期的用户剔出队列

通过zcard命令可以知道当前的队列的长度

通过zrem命令将用户剔出队列

image-20201006180633410

使用一个zset来存储每个用户当前的操作次数,value标识用户,score表示操作次数

每次用户成功访问就增加操作次数,如果用户的操作次数超过阈值则剔出队列

使用zincrby命令可以增加用户的操作次数

整体逻辑

image-20201006181756551

为了保证整个流程的原子性,上面的逻辑需要通过Lua脚本来实现

如果redis采用了集群部署,因为整个流程涉及到了多个key的操作,所以还需要为每个key打tag

操作次数和过期时间的阈值也放到redis中,这样就可以实现动态修改规则

待完善

  • 与spring剥离解耦(目前通过spring的filter实现,服务器仍会建立连接,只是不处理请求)
  • 动态配置api(目前api配置是配在spring的filter里)
  • 监控功能