1.今日博客学习内容
1.1 如何限制进入系统的请求在1w之内,限流的设计方案是什么?
Redis实现限定窗口限流
Redis中的固定窗口限流是使用
incr
命令实现的,incr
命令通常用来自增计数;如果我们使用时间戳信息作为 key,自然就可以统计每秒的请求量了,达到限定请求量,以此达到限流目的。这里有两点要注意。
对于不存在的 key,第一次新增时,value 始终为 1。
INCR
和EXPIRE
命令操作应该在一个原子操作中提交,以保证每个 key 都正确设置了过期时间,不然会有 key 值无法自动删除而导致的内存溢出。
Redis实现滑动窗口限流
这里主要使用
ZSET
有序集合来实现滑动窗口限流,ZSET
集合有下面几个特点:
- ZSET 集合中的 key 值可以自动排序。
- ZSET 集合中的 value 不能有重复值。
- ZSET 集合可以方便的使用 ZCARD 命令获取元素个数。
- ZSET 集合可以方便的使用 ZREMRANGEBYLEX 命令移除指定范围的 key 值。
我们可以将请求打造成一个zset数组,当每一次请求进来的时候,value保持唯一,可以用UUID生成,而score可以用当前时间戳表示,因为score我们可以用来计算当前时间戳之内有多少的请求数量。而zset数据结构也提供了range方法让我们可以很轻易的获取到2个时间戳内有多少请求
Redis实现令牌桶算法限流
令牌桶算法提及到输入速率和输出速率,当输出速率大于输入速率,那么就是超出流量限制了。
也就是说我们每访问一次请求的时候,可以从Redis中获取一个令牌,如果拿到令牌了,那就说明没超出限制,而如果拿不到,则结果相反。
我们可以使用Redis的List数据结构实现令牌桶算法。
List的leftPop来获取令牌。
使用Java的定时任务,定时往List中rightPush令牌,当然令牌也需要唯一性,UUID进行生成。