几种限流、控频策略对比几种限流、控频策略对比
这里主要讨论以下几种方式,有更好的建议,欢迎留言
基于数据库(Mysql为例)的统计进行限流
基于redis自增长及过期策略的限流
基于内存(linkedlist为例)的限流
基于木桶算法的限流
本次介绍,主要关注实现策略、控制粒度及时间窗口问题,示例代码中可能存在编码不规范的情况,请忽略
1. 基于数据库的统计进行限流基于数据库的统计进行限流
基于数据库的统计进行限流主要思想是,将每次的信息连同时间写入一条数据库记录,然后根据时间范围统计信息,决策
是否需要限流。举例如下:
场景:场景:
密码1分钟内输入错误次数超限,冻结账号。
要点:要点:
1. 登录失败时,将用户的登录名、登录时间写入数据库记录。
2.登录前根据登录名,查询近1分钟登录失败的次数。
3.判断登录次数是否大于设定的超限值,如果大于则进行冻结处理,如果未超过,正常执行登录判断(登录失败时执行第
一要点)。
代码要点:代码要点:
select count(登录名) from 登录错误记录表 where 登录名='登录名' and 登录时间 > DATE_SUB(NOW(), INTERVAL 1 MINUTE)
分析:分析:
此方案的粒度控制在于代码逻辑的堆砌和数据库的设计,较为灵活,时间窗口为最近一分钟(假定),属于滑动时间窗
口;由于时基于数据库的,分布式部署的情况下也能有效,不足之处在于会增加数据库的压力。
2. 基于基于redis自增长及过期策略的限流自增长及过期策略的限流
基于redis自增长及过期策略主要思想是:在redis中维护一个key,并设置过期时间,每次控制前读取该key,如果该key对
应的值大于了限制值,则被限制,如果不大于,则通过redis的incr对key进行自增长处理,如果为空,则重新维护key,并设置
过期时间。如此往复达到限流目的。
场景:场景:
对接口进行会话级别的访问控制
要点要点
1. 读取key,根据key对应值value的不同情况进行处理:
a. value不存在,设置set key 及过期时间
b. value大于限定值,限流
c. valuex不大于限定值,value自增长1
代码要点:代码要点:
涉及到的redis命令如下:
## 设置key的值5秒过期
set kkk 1 EX 5
### 获取key的值
get kkk
### 自增长
incr kkk
### 手动设置过期时间
expire kkk 5
代码示例
private boolean accessCheck(HttpSession session) {
String key = "ACCESS"+session.getId();
long current = 1;
// key不存在,进行设置
if( valueOperations.get(key) == null){
//一步到位
//valueOperations.set(key,1,5,TimeUnit.SECONDS);
// 也可以分两步设置
valueOperations.increment(key);
valueOperations.getOperations().expire(key,5,TimeUnit.SECONDS);
}else {
// key已经存在了,自增+1
valueOperations.increment(key);
current = Long.parseLong(valueOperations.get(key));
}