常见限流算法实现
1. 固定窗口
算法思想:对每一个请求进行计数,每间隔一段时间清除统计的数量,如果期间请求计数达到上限则请求失败。
实现:一般分为多线程实现和单线程实现,多线程实现较为简单,即单独开辟一个定时任务去清除统计的请求数,但是耗费资源;本文主要展示单线程的无锁实现,也可使用有锁实现,差别不大。
//单线程无锁实现
public class FixedWindow {
//复位间隔时间
private final long interval;
//最大凭证数
private final int limit;
//当前剩余的凭证数
private final AtomicInteger current;
//上一次复位时间
private final AtomicLong lastClearTime;
public FixedWindow(int limit){
//每秒限制limit个请求
this(1000, limit);
}
public FixedWindow(long interval, int limit) {
this.interval = interval;
this.limit = limit;
lastClearTime = new AtomicLong();
current = new AtomicInteger(limit);
}
/**
* 请求凭证
* @param permit 凭证数
* @return 成功、失败
*/
public boolean tryAcquire(int permit){
reset();
while (true){
int num = current.get();
if(num < permit){
return false;
}
if(current.compareAndSet(num, num - permit)){
break;
}
}
return true;
}
/**
* 每隔一段时间进行复位
*/
private void reset(){
//采用死循环,避免多线程竞争失败的线程,先执行后面获取凭证的流程导致失败
while (true){
long now = System.currentTimeMillis();
long last = lastClearTime.get();
if(now - last > interval){
if(lastClearTime.compareAndSet(last, now)){
current.set(limit);
break;
}
}else {
break;
}
}
}
}
2. 滑动窗口
待补充
3.令牌桶
待补充