限流算法-令牌桶实现

📅 发布时间:2026/7/7 21:15:27 👁️ 浏览次数:
限流算法-令牌桶实现
一 核心逻辑不要用定时器不能说起一个线程每秒往桶里加100令牌。 如果限流的维度很大比如按10000SKU分别限流起10000个线程会把cpu拖垮。工业级解法惰性填充我们不需要实时加令牌只需要在请求进来的一瞬间根据当前时间与上一次请求时间的差值动态计算这段时间该补多少令牌。二 代码实现class TokenBucketRateLimiter {private int capacity; //最大容量private double refillRate ; //每秒新增令牌数double currentTokens ; //当前桶内令牌long lastRefillTimeStamp; //上次填充令牌的时间戳//构造函数//尝试获取一个令牌 true放行false限流public synchronized boolean tryAcquire(){long now system.nanoTime();//惰性填充计算自上次请求以来需要新增多少令牌long seconds ( now - lastRefillTimeStamp)/1000 //时间转换为秒//更新令牌数不能超过容量currentTokens min(capacity, currentTokensseconds*refillRate)//判断是否足够扣减if(currentTokens 1.0){currentTokens --;return true;}}return false ;}问题1 为什么要用synchronized ?在高并发下多个线程执行tryAcquire。 如果不加锁currentTokens的读取和更新会出现竞态条件导致限流失效或者不准。 在单机环境下Synchronized性能足够如果追求更好性能可以使用AtomicReference配合CAS来实现无锁化。问题2 这个算法怎么处理突发流量令牌桶中如果积攒了令牌面对突发流量可以一定程度上应对同时令牌桶又在以一定频率产生令牌。问题3 在分布式环境下限流的实现Redis lua脚本1) 将lastRefillTime 和 currentTokens存入redis2) lua脚本保障读取计算更新这3步是原子操作