需求
- 分布式限流
- 限制队列长度,同一时间内只能支持一定用户的使用
- 限制用户在队列内的时间和操作次数,超过时间或次数即退出队列重新排队
- 支持队列动态配置
设计
数据结构
使用一个zset来模拟一个用户队列,其中score的值表示用户入队时的时间戳(图中只是为了表示方便,实际为时间戳)
通过zremrangebyscore命令可以很方便地将过期的用户剔出队列
通过zcard命令可以知道当前的队列的长度
通过zrem命令将用户剔出队列
使用一个zset来存储每个用户当前的操作次数,value标识用户,score表示操作次数
每次用户成功访问就增加操作次数,如果用户的操作次数超过阈值则剔出队列
使用zincrby命令可以增加用户的操作次数
整体逻辑
为了保证整个流程的原子性,上面的逻辑需要通过Lua脚本来实现
如果redis采用了集群部署,因为整个流程涉及到了多个key的操作,所以还需要为每个key打tag
操作次数和过期时间的阈值也放到redis中,这样就可以实现动态修改规则
待完善
- 与spring剥离解耦(目前通过spring的filter实现,服务器仍会建立连接,只是不处理请求)
- 动态配置api(目前api配置是配在spring的filter里)
- 监控功能