瞧瞧别人家的限流,那叫一个优雅!

向量数据库大模型关系型数据库

大家好,我是苏三,又跟大家见面了。

文末留言送书了

前言

去年夏天某个凌晨,我接到某金融平台报警:支付接口错误率飙升至35%。

赶到机房时,发现数据库连接池耗尽,大量请求堆积成山——这就是典型的未做限流防护 的灾难现场。

就像高速公路不设收费站,高峰期必然堵成停车场。

限流的本质 不是拒绝服务,而是用可控的牺牲保护核心链路

某电商大促时,他们用令牌桶算法将秒杀接口QPS限制在5万,虽然流失了20%的突发流量,但保住了99%的核心交易成功率。

1 常用限流方案

1.1 固定窗口计数器

核心原理:
以固定时间窗口(如1秒)为周期,统计周期内请求数,超过阈值则拒绝后续请求。

picture.image

具体代码实现如下:

  
// 线程安全实现(AtomicLong优化版)  
public class FixedWindowCounter {  
    private final AtomicLong counter = new AtomicLong(0);  
    private volatile long windowStart = System.currentTimeMillis();  
    private final int maxRequests;  
    private final long windowMillis;  
  
    public boolean tryAcquire() {  
        long now = System.currentTimeMillis();  
        if (now - windowStart > windowMillis) {  
            if (counter.compareAndSet(counter.get(), 0)) {  
                windowStart = now;  
            }  
        }  
        return counter.incrementAndGet() <= maxRequests;  
    }  
}  

致命缺陷:
假设设置1秒100次限制,0.9秒时突发100次请求,下一秒0.1秒又放行100次,实际两秒内通过200次。

就像红绿灯切换时车辆抢行,容易引发"临界点突刺"。

适用场景:
日志采集、非关键性接口的粗粒度限流

1.2 滑动窗口

核心原理:
将时间窗口细分为更小的时间片(如10秒),统计最近N个时间片的请求总和。

picture.image

基于Redis的Lua脚本如下:

  
// Redis Lua实现滑动窗口(精确到毫秒)  
String lua = """  
    local now = tonumber(ARGV  
    local window = tonumber(ARGV  
    local key = KEYS[1]  
      
    redis.call('ZREMRANGEBYSCORE', key, '-inf', now - window)  
    local count = redis.call('ZCARD', key)  
      
    if count < tonumber(ARGV then  
        redis.call('ZADD', key, now, now)  
        redis.call('EXPIRE', key, window/1000)  
        return 1  
    end  
    return 0  
    """;  

技术亮点:
某证券交易系统采用滑动窗口后,将API异常率从5%压降至0.3%。

通过Redis ZSET实现时间切片,误差控制在±10ms内。

优势对比

| 指标 | 固定窗口 | 滑动窗口 | | --- | --- | --- | | 时间精度 | 1秒 | 100ms | | 临界突刺问题 | 存在 | 消除 | | 实现复杂度 | 简单 | 中等 |

2.3 漏桶算法

核心原理:
请求像水流一样进入漏桶,系统以固定速率处理请求。

桶满时新请求被丢弃。

picture.image

具体实现如下:

  
// 漏桶动态实现(Semaphore优化版)  
public class LeakyBucket {  
    private final Semaphore permits;  
    private final ScheduledExecutorService scheduler;  
  
    public LeakyBucket(int rate) {  
        this.permits = new Semaphore(rate);  
        this.scheduler = Executors.newScheduledThreadPool(1);  
        scheduler.scheduleAtFixedRate(() -> permits.release(rate), 1, 1, TimeUnit.SECONDS);  
    }  
  
    public boolean tryAcquire() {  
        return permits.tryAcquire();  
    }  
}  

技术痛点:
某智能家居平台用此方案,确保即使10万台设备同时上报数据,系统仍按500条/秒的速率稳定处理。

但突发流量会导致队列积压,就像用漏斗倒奶茶——珍珠容易卡住。

适用场景:
IoT设备控制指令下发、支付渠道限额等需要严格恒定速率的场景

1.4 令牌桶算法

核心原理:
以固定速率生成令牌,请求需获取令牌才能执行。

突发流量可消耗桶内积攒的令牌。

picture.image

具体实现如下:

  
// Guava RateLimiter高级用法  
RateLimiter limiter = RateLimiter.create(10.0, 1, TimeUnit.SECONDS); // 初始预热  
limiter.acquire(5); // 尝试获取5个令牌  
  
// 动态调整速率(需反射实现)  
Field field = RateLimiter.class.getDeclaredField("tokens");  
field.setAccessible(true);  
AtomicDouble tokens = (AtomicDouble) field.get(limiter);  
tokens.set(20); // 突发时注入20个令牌  

实战案例:
某视频平台用此方案应对热点事件:平时限制10万QPS,突发时允许3秒内超限50%,既防雪崩又保用户体验。

动态特性

  • 正常时限制QPS
  • 突发时允许透支
  • 持续突发会耗尽令牌

2 生产环境实战

2.1 网关层分布式限流

某电商双11方案:通过Redis+Lua实现分布式计数,配合Nginx本地缓存,在网关层拦截了83%的恶意请求。

picture.image

2.2 自适应熔断机制

我们还需要自适应熔断机制。

某社交平台用此方案,在突发流量时自动将限流阈值从5万降到3万,等系统恢复后再逐步提升。

picture.image

3 避坑指南与性能优化

3.1 致命误区

在数据库连接池前做限流!

某公司曾因此导致连接泄漏,最终撑爆数据库。

正确做法应遵循熔断三原则

  1. 快速失败:在入口层拦截无效请求
  2. 动态降级:核心服务保留最小资源
  3. 自动恢复:熔断后渐进式放量

3.2 性能优化

某金融系统通过JMH测试发现,使用LongAdder替代AtomicLong,限流吞吐量提升220%。

picture.image

性能优化手段:减少CAS竞争 和 分段锁基座。picture.image

总结

上面列举了工作中最常用的4种限流方案。

对于不同的业务场景,我们需要选择不同的限流方案。

picture.image

限流的黄金法则如下:picture.image

记住:好的限流方案就像高铁闸机——既保证通行效率,又守住安全底线。

文末送书

为了感谢一路支持苏三的小伙们,今天特地给大家送一点小福利。规则非常简单:在本文留言,我会挑选其中最用心的3位留言者(不一定是点赞最多的),每人获取1本书。

后面我会朋友圈公布中奖名单,给你免费包邮到家!这些书是由清华大学出版社提供的,感谢赞助。

《Node.js全栈开发从入门到项目实战

picture.image

本书从Node.js的基本概念讲起,逐步深入基于Nodejs的主流开发框架技术, 结合完整的项目案例重点介绍基于Node.js的微信商城项目开发的全过程,帮助读者系统地掌握Node.js全栈开发技术,从而具备开发商业级应用的能力。
本书共15章,分为3篇。
第1篇为Node.js开发基础知识,主要介绍Node.js入门知识、Node.js模块化管理、JavaScript基础知识、Node.js的内置模块、数据库操作等。

第2篇为Node.js开发主流框架,主要介绍Express框架、Koa框架和Egg框架。

第3篇为项目实战,主要基于Node.js+MySQL+Vue,开发一个完整的微信商城项目,演示完整的商业级全栈项目开发的全过程,并简单介绍Node.js程序、微信小程序和Vue程序性能优化涉及的相关知识。
本书通俗易懂,案例典型,实用性强,特别适合Node.js全栈开发的入门和进阶人员阅读,也适合前后端项目开发人员和Java程序员等编程爱好者阅读,还适合作为高校和相关培训机构的实践教材。

最后说一句(求关注,别白嫖我)

如果这篇文章对您有所帮助,或者有所启发的话,帮忙扫描下发二维码关注一下,您的支持是我坚持写作最大的动力。

求一键三连:点赞、转发、在看。

关注公众号:【苏三说技术】,在公众号中回复:面试、代码神器、开发手册、时间管理有超赞的粉丝福利,另外回复:加群,可以跟很多BAT大厂的前辈交流和学习。

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
字节跳动 NoSQL 的实践与探索
随着 NoSQL 的蓬勃发展越来越多的数据存储在了 NoSQL 系统中,并且 NoSQL 和 RDBMS 的界限越来越模糊,各种不同的专用 NoSQL 系统不停涌现,各具特色,形态不一。本次主要分享字节跳动内部和火山引擎 NoSQL 的实践,希望能够给大家一定的启发。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论