0
点赞
收藏
分享

微信扫一扫

接口防抖

洛茄 02-07 09:00 阅读 3

令牌桶算法

原理

令牌桶算法是一种常用的流量控制算法,也可以用于接口防抖。其核心思想是系统以固定的速率向一个“令牌桶”中放入令牌,每个请求需要从令牌桶中获取一个或多个令牌才能被处理。如果令牌桶中没有足够的令牌,请求将被拒绝或等待。

代码示例(Java)

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class TokenBucket {
private final int capacity; // 令牌桶容量
private final int rate; // 令牌生成速率(每秒生成的令牌数)
private int tokens; // 当前令牌数量
private long lastRefillTime; // 上次填充令牌的时间

public TokenBucket(int capacity, int rate) {
this.capacity = capacity;
this.rate = rate;
this.tokens = capacity;
this.lastRefillTime = System.currentTimeMillis();

// 定时填充令牌
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(this::refill, 1, 1, TimeUnit.SECONDS);
}

// 填充令牌
private synchronized void refill() {
long now = System.currentTimeMillis();
int newTokens = (int) ((now - lastRefillTime) / 1000 * rate);
tokens = Math.min(capacity, tokens + newTokens);
lastRefillTime = now;
}

// 尝试获取令牌
public synchronized boolean tryAcquire() {
refill();
if (tokens > 0) {
tokens--;
return true;
}
return false;
}

public static void main(String[] args) {
TokenBucket tokenBucket = new TokenBucket(100, 10);
if (tokenBucket.tryAcquire()) {
System.out.println(请求被处理);
} else {
System.out.println(请求被拒绝,令牌不足);
}
}
}

代码解释

  • capacity 表示令牌桶的最大容量,rate 表示每秒生成的令牌数。
  • refill 方法用于定时填充令牌,根据时间差计算需要填充的令牌数量,并更新当前令牌数量。
  • tryAcquire 方法用于尝试获取令牌,如果令牌桶中有足够的令牌,则减少一个令牌并返回 true;否则返回 false

信号量机制

原理

信号量是一种并发控制机制,它维护了一个计数器,表示可用的资源数量。每个请求需要获取一个信号量才能继续执行,如果信号量计数器为 0,则请求需要等待或被拒绝。

代码示例(Java)

import java.util.concurrent.Semaphore;

public class SemaphoreDebounce {
private final Semaphore semaphore;

public SemaphoreDebounce(int permits) {
this.semaphore = new Semaphore(permits);
}

public boolean canExecute() {
return semaphore.tryAcquire();
}

public void release() {
semaphore.release();
}

public static void main(String[] args) {
SemaphoreDebounce debounce = new SemaphoreDebounce(1);
if (debounce.canExecute()) {
try {
System.out.println(执行接口逻辑);
} finally {
debounce.release();
}
} else {
System.out.println(短时间内重复请求,不执行接口逻辑);
}
}
}

代码解释

  • Semaphore 类用于实现信号量机制,构造函数中的 permits 参数表示可用的信号量数量。
  • canExecute 方法调用 tryAcquire 方法尝试获取一个信号量,如果获取成功则返回 true,否则返回 false
  • release 方法用于释放一个信号量,使其他请求可以继续获取。

分布式锁

原理

在分布式系统中,可以使用分布式锁来实现接口防抖。当一个请求到达时,尝试获取分布式锁,如果获取成功,则执行接口逻辑;如果获取失败,则说明有其他请求正在处理,当前请求被拒绝。

代码示例(Redis 分布式锁)

import redis.clients.jedis.Jedis;

public class RedisDistributedLock {
private static final String LOCK_KEY = api_debounce_lock;
private static final int LOCK_EXPIRE_TIME = 500; // 锁的过期时间,单位:毫秒
private final Jedis jedis;

public RedisDistributedLock() {
this.jedis = new Jedis(localhost, 6379);
}

public boolean tryLock() {
String result = jedis.set(LOCK_KEY, locked, NX, PX, LOCK_EXPIRE_TIME);
return OK.equals(result);
}

public void unlock() {
jedis.del(LOCK_KEY);
}

public static void main(String[] args) {
RedisDistributedLock lock = new RedisDistributedLock();
if (lock.tryLock()) {
try {
System.out.println(执行接口逻辑);
} finally {
lock.unlock();
}
} else {
System.out.println(短时间内重复请求,不执行接口逻辑);
}
}
}

代码解释

  • 使用 Redis 的 SET 命令并设置 NX(仅在键不存在时设置)和 PX(设置过期时间)选项来实现分布式锁。
  • tryLock 方法尝试获取锁,如果返回 "OK" 则表示获取成功;否则表示锁已被其他请求占用。
  • unlock 方法用于释放锁,通过删除 Redis 中的键来实现。

这些方法都可以有效地实现后端接口防抖,具体选择哪种方法取决于实际的业务需求和系统环境。

举报

相关推荐

0 条评论