0
点赞
收藏
分享

微信扫一扫

接口防抖

洛茄 02-07 09:00 阅读 1

令牌桶算法

原理

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

代码示例(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 条评论