当前位置: 首页
AI教程
常见限流与控频策略对比分析

常见限流与控频策略对比分析

热心网友 时间:2026-06-16
转载

对四种限流策略进行对比:基于数据库实现滑动窗口,适合登录控制;基于Redis固定窗口,适合接口访问控制;基于内存滑动窗口,实现应用级限流;木桶算法滑动窗口,可根据应用位置灵活部署,能应对分布式环境。

本文将深入探讨几种常见的限流方案,每种方案都具备独特的适用场景。我们将从实现策略、控制粒度以及时间窗口的处理方式等维度进行详细分析。请注意,示例代码可能存在不够规范之处,核心目标是帮助理解设计思路。

1. 基于数据库统计的限流方法

基于数据库实现限流,核心思路非常直观:每次操作时,向数据库写入一条包含时间戳的记录,随后根据设定的时间范围进行统计,判断是否达到限流阈值。下面通过一个具体场景帮助理解。

适用场景:用户密码在1分钟内输入错误次数过多,系统自动冻结账号。

要点:

  • 登录失败时,将登录名和登录时间写入数据库记录。
  • 登录前,根据登录名查询最近1分钟内的失败次数。
  • 判断失败次数是否超过预设阈值,若超过则冻结账号,否则执行正常登录流程(登录失败后再写入记录)。

代码要点:

select count(登录名) from 登录错误记录表 where 登录名='登录名' and 登录时间 > DATE_SUB(NOW(), INTERVAL 1 MINUTE)

分析:
该方案的粒度控制可通过代码逻辑与数据库设计灵活调整,时间窗口设为最近一分钟,属于典型的滑动时间窗口。由于依赖数据库存储,它同样适用于分布式环境。然而,缺点显而易见——随着请求量增加,数据库压力会急剧上升。

2. 基于Redis自增及过期策略的限流方案

基于Redis实现限流,核心思路如下:在Redis中维护一个带有过期时间的键(key),每次操作前先读取该键的值。如果当前值已超过限制,则触发限流;否则通过INCR命令进行自增,若键不存在,则创建并设置过期时间。如此循环往复。

适用场景:对接口实施会话级别的访问频率控制。

要点:

  • 读取键值,根据value的不同情况分别处理:若键不存在,则设置键并指定过期时间;若value大于限定值则触发限流;若value未超过限定值则执行自增操作。

代码要点(Redis命令):

## 设置key的值5秒过期
set kkk 1 EX 5

### 获取key的值
get kkk

### 自增长
incr kkk

### 手动设置过期时间
expire kkk 5

代码示例:

private boolean accessCheck(HttpSession session) {
    String key = "ACCESS" + session.getId();
    long current = 1;
    // key不存在,进行设置
    if( valueOperations.get(key) == null){
        // 一步到位
        //valueOperations.set(key,1,5,TimeUnit.SECONDS);
        // 也可以分两步设置
        valueOperations.increment(key);
        valueOperations.getOperations().expire(key,5,TimeUnit.SECONDS);
    } else {
        // key已经存在了,自增 1
        valueOperations.increment(key);
        current = Long.parseLong(valueOperations.get(key));
    }
    if(current > 20){
        throw new RuntimeException("访问次数过多,请稍后再试");
    }
    return true;
}

分析:
Redis方案同样支持分布式环境,时间窗口为固定窗口(取决于设置的过期时间)。凭借Redis的高性能,该方案能够应对较大的流量冲击。控制粒度则取决于具体的设计细节。

3. 基于内存(以LinkedList为例)的限流方案

基于内存的限流策略,实质是在内存中维护一个时间窗口的数据结构,通过统计窗口内的请求数量来做出限流决策。

适用场景:对接口调用频率进行控制。

要点:

  • 维护一个按时间升序排列的请求列表(避免每次全量扫描)。
  • 移除超出时间窗口的旧数据。
  • 在列表末尾添加最新的时间戳。

代码要点(以LinkedList为例):

private boolean accessCheckByLinkedList(){
    synchronized(accessList) {
        Date data = null;
        Date now = new Date();
        if(accessList.size() > 0){
            data = accessList.getFirst();
            while (data != null && now.getTime() - data.getTime() > 5000) {
                accessList.removeFirst();
                if(accessList.size() > 0){
                    data = accessList.getFirst();
                } else {
                    data = null;
                }
            }
            if (accessList.size() > 5) {
                throw new RuntimeException("访问频率过高");
            }
        }
        accessList.add(new Date());
    }
    return true;
}

分析:
内存限流的控制粒度完全取决于设计者的实现水平。由于是内存操作,必须妥善处理线程同步(虽然使用ConcurrentHashMap等并发容器可以减少部分同步问题,但排序仍需注意)以及高并发下的竞争条件。其控制粒度为应用级别,能够从应用层面直接拦截流量,避免因负载均衡策略失效或异常情况导致后端服务被冲垮。

4. 基于木桶算法的限流方案

木桶算法的思路更为形象:维护一个固定容量的“池”,每次请求消耗池中的存量,同时通过后台任务持续向池中添加资源,并确保存量始终不超过最大值。

适用场景:应用级别接口请求频率控制。

要点:

  • 当增加池中存量时,若达到最大值则暂停新增。
  • 当使用池中存量时,若存量降至0以下则触发限流。
  • 确保池既不会被撑爆,也不会被透支。

代码要点:

public class BucketAlgorithmTest {
    public static void main(String[] args) throws InterruptedException {
        // 定时添加资源
        new Thread(()-> {
            while (true){
                Bucket.add();
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        Thread.sleep(200);
        // 若初始默认值为满则可省略此步骤
        // 定时消耗资源,模拟控制逻辑
        new Thread(()->{
            int errorcout = 0;
            while (errorcout < 10) {
                try {
                    Bucket.get();
                    Thread.sleep(40);
                } catch (Exception e) {
                    errorcout++;
                    e.printStackTrace();
                    try {
                        Thread.sleep(100);
                    }catch (Exception ee){}
                }
            }
        }).start();
    }
}

class Bucket{
    /**
     * 当前可用量
     */
    private static Integer currentSize = 0;
    /**
     * 最大容量
     */
    private final static int totalSize = 20;
    /**
     * 添加资源
     */
    public static void add(){
        synchronized (currentSize) {
            if(currentSize < totalSize) {
                currentSize++;
                System.out.println("[添加    ]可用" + Bucket.getCurrentSize());
            }
        }
    }
    /**
     * 消耗资源
     */
    public static void get(){
        synchronized (currentSize) {
            if(currentSize > 0) {
                currentSize--;
                System.out.println("[使用---]可用" + Bucket.getCurrentSize());
            }else {
                throw new RuntimeException("当前无可用资源,请求被限流");
            }
        }
    }
    public static Integer getCurrentSize(){
        return currentSize;
    }
}

为了方便理解,这里贴一张运行结果:

在这里插入图片描述

分析:
木桶算法的可调性很强,具体效果取决于对原理的理解深度。在突发大流量冲击下,恢复时间可能相对较长。它本质上是一种“滑动流量”窗口,而非严格的时间窗口。该策略的数据可以存储在内存、数据库或Redis中,应用场景也可灵活定制,既可作为应用级限流,也可作为负载均衡层面的策略补充。

限流方案对比总结

方案 时间窗口 基于 分布式环境 应用范围
数据库统计 滑动 数据库 支持 登录次数控制
Redis自增 固定 Redis 支持 接口频率控制
内存列表 滑动 内存 不支持 应用级频率控制
木桶算法 滑动 内存/Redis/数据库 支持 灵活配置
来源:https://cloud.tencent.com.cn/developer/article/2689572

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
Claude Code 必知的14个高效工作流,让你的开发效率提升300%

Claude Code 必知的14个高效工作流,让你的开发效率提升300%

Claude Code 常用工作流 先分享几项核心判断:Claude Code 真正强大的地方,并非仅仅在于它能编写代码——而是它让“编码”这件事本身变得更加高效且可控。你大概率遇到过这类场景:接手一个陌生项目,花了一整天才能理清架构;线上出现报错,翻遍日志也找不到根本原因;想要重构遗留代码,又担心

时间:2026-07-09 17:49
阿里云通义AIGC平台完全指南:设计师AI生产力革命

阿里云通义AIGC平台完全指南:设计师AI生产力革命

一、写在前面:为什么设计师需要关注AIGC? 如果你还在手动一张一张制作海报、反复修改客户口中“感觉不对”的配色方案、为电商详情页准备几十张不同场景的产品图——那么你一定经历过这些痛点: 创意瓶颈:脑海中有画面,但手绘无法呈现 重复劳动:调整尺寸、更换背景、批量生成变体消耗了大量时间精力 成本焦虑:

时间:2026-07-09 16:48
零基础毕设代码二次开发:3文件定位法及Vue/Java修改对照表

零基础毕设代码二次开发:3文件定位法及Vue/Java修改对照表

每年一到毕业季,计算机专业的同学总会陷入一个共同的怪圈:从 GitHub 上扒下来一套代码,或者用 AI 生成一个项目,看起来挺完整的,可导师一句“加个筛选条件”或“换个页面颜色”,瞬间就懵了——不敢改,不会改,怕改崩。是不是很熟悉? 一、为什么AI生成的毕设代码你 "不敢改 "? 1 1 毕业生的三大

时间:2026-07-09 16:46
反向海淘订单系统:状态机与分布式事务实战设计

反向海淘订单系统:状态机与分布式事务实战设计

先分享一个反直觉的结论:反向海淘订单管理的真正挑战,往往不在于业务逻辑本身,而在于状态流转。一个订单的生命周期拉长到跨国运输,中间涉及的环节多、系统多、参与者多,状态稍有错乱就可能引发连锁事故。Taocarts团队在实践中踩了不少坑,最终沉淀下来的这套状态机与分布式事务方案,成功解决了这一复杂难题。

时间:2026-07-09 16:46
AI并未抢走程序员饭碗而是更新了编程菜单

AI并未抢走程序员饭碗而是更新了编程菜单

AI并未大规模替代程序员,而是改变了职业结构。重复性编码岗位需求下降35%至15%,而AIAgent开发等岗位需求激增187%。开发者焦虑从“被替代”转向“跟不上变化”,60%程序员已使用AI辅助编程。人的核心价值转向架构设计、技术决策和审查AI生成代码,AI技能带来16%薪资溢价。

时间:2026-07-09 16:46
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 热门数据榜