令牌桶算法与漏桶算法 \color{#FF1493}{令牌桶算法与漏桶算法} 令牌桶算法与漏桶算法
仰望天空,妳我亦是行人.✨
个人主页——微风撞见云的博客
《数据结构与算法》专栏的文章图文并茂生动形象简单易学!欢迎大家来踩踩~
《Java学习笔记》专栏的文章是本人在Java学习中总结的一些知识点~
《每天一点小知识》专栏的文章可以丰富你的知识库,滴水成河~
《Redis》专栏的文章是在学习Redis时,整理的笔记与记录的思考~
《RabbitMQ》专栏的文章是在学习尚硅谷课程时整理的笔记,方便复习巩固~
希望本文能够给读者带来一定的帮助~文章粗浅,敬请批评指正!
令牌桶算法和漏桶算法都是用于限制请求速率的流量控制算法,通常用于网络、服务器和API等场景中,以防止突发的流量超出系统的处理能力。它们的主要区别在于如何处理流量超出限制的情况以及在限制流量时的行为。
令牌桶算法的核心思想是,系统维护一个固定容量的令牌桶,这个桶以恒定的速率往里面添加令牌,每个令牌代表一个请求的许可。当一个请求到达时,它需要从令牌桶中获取一个令牌,只有当令牌桶中有足够的令牌时,请求才会被允许通过,否则请求会被拒绝或等待。
令牌桶算法的关键参数包括:
算法的基本工作流程如下:
令牌桶算法的优点是可以处理瞬时的流量峰值,如果桶中有足够的令牌,请求才可以被立即处理。同时,令牌桶算法也可以平滑地控制请求速率。
import java.util.concurrent.Semaphore;
class TokenBucket {
private final int capacity; // 令牌桶容量
private final long generationInterval; // 令牌生成间隔时间(毫秒)
private long lastGenerationTime; // 上次生成令牌的时间
private int tokens; // 当前令牌数量
private final Semaphore semaphore; // 信号量用于控制请求
public TokenBucket(int capacity, int tokensPerSecond) {
this.capacity = capacity;
this.generationInterval = 1000 / tokensPerSecond;
this.tokens = capacity;
this.semaphore = new Semaphore(1);
this.lastGenerationTime = System.currentTimeMillis();
}
public boolean tryAcquire() {
// 获取信号量,确保令牌桶更新的线程独占执行
try {
semaphore.acquire();
long currentTime = System.currentTimeMillis();
long elapsedTime = currentTime - lastGenerationTime;
// 计算新生成的令牌数量
int newTokens = (int) (elapsedTime / generationInterval);
if (newTokens > 0) {
tokens = Math.min(capacity, tokens + newTokens);
lastGenerationTime = currentTime;
}
// 尝试获取令牌
if (tokens > 0) {
tokens--;
return true;
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
semaphore.release();
}
return false;
}
}
测试:
漏桶算法的思想是,系统维护一个固定容量的漏桶,当请求到达时,漏桶以固定速率处理请求,不管请求的到达速率如何。如果漏桶已满,多余的请求将会被丢弃或排队等待。
漏桶算法的关键参数包括:
算法的基本工作流程如下:
漏桶算法的特点是无论请求的到达速率如何,处理请求的速率都是恒定的,因此可以用来平滑流量并限制突发请求。
import java.util.concurrent.TimeUnit;
class LeakyBucket {
private final int capacity; // 漏桶容量
private final int rate; // 漏水速率 (请求/秒)
private int water; // 当前水量
private long lastLeakTime; // 上次漏水时间
public LeakyBucket(int capacity, int rate) {
this.capacity = capacity;
this.rate = rate;
this.water = 0;
this.lastLeakTime = System.nanoTime();
}
public synchronized boolean tryConsume() {
long now = System.nanoTime();
long elapsedNanos = now - lastLeakTime;
int leaked = (int) TimeUnit.NANOSECONDS.toSeconds(elapsedNanos) * rate;
if (leaked > 0) {
water = Math.max(0, water - leaked);
lastLeakTime = now;
}
if (water < capacity) {
water++;
return true;
} else {
return false; // 漏桶已满,请求被拒绝
}
}
}
测试:
令牌桶算法和漏桶算法都是有用的限流工具,可用于保护系统免受过多请求的冲击。通过使用这些算法,我们可以更好地管理和控制流量,确保系统的稳定性和可用性。
这两种算法都有自己的应用场景,选择哪种算法取决于需求。如果需要平滑流量并确保恒定的处理速率,可以选择漏桶算法;如果需要允许瞬时的流量峰值,可以选择令牌桶算法。
初学一门技术时,总有些许的疑惑,别怕,它们是我们学习路上的点点繁星,帮助我们不断成长。
积少成多,滴水成河。文章粗浅,希望对大家有帮助!