游乐游手机版
首页/AI教程/文章详情

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

时间:2026-06-16 15:52
对四种限流策略进行对比:基于数据库实现滑动窗口,适合登录控制;基于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
上一篇AI推荐品牌时你的内容被忽略的真正原因是什么 下一篇VSCode插件快餐教程第8讲:LSP文本同步完整实现详解
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
Windows Docker Desktop RabbitMQ生产级部署完整指南
AI教程 · 2026-06-29

Windows Docker Desktop RabbitMQ生产级部署完整指南

前言 在 Windows 本地开发环境中,直接安装 RabbitMQ 确实颇为周折:需要单独配置 Erlang 运行环境、手动管理环境变量、服务启停全凭手工操作。更令人困扰的是,版本兼容冲突、端口占用、环境不一致等问题层出不穷。笔者见过不少开发者为搭建环境就得耗费整整半天时间。 相比之下,借助 Do

AI搜索重构制造业采购逻辑的阿里云企业级GEOCMS优化实践
AI教程 · 2026-06-29

AI搜索重构制造业采购逻辑的阿里云企业级GEOCMS优化实践

先分享一个切实感受。过去两年,我们与福建制造企业合作较为频繁,发现一个非常突出的现象:超过80%的企业官网,产品参数仍然存放在PDF或图片中。AI爬虫?根本无法抓取。这些企业技术实力不弱、资质证照齐全、应用案例也丰富,但在AI搜索这一全新战场上,它们几乎处于隐身状态。 一、一个正在发生的行业变化 A

阿里云Token Plan团队版功能价格与省钱购买指南
AI教程 · 2026-06-29

阿里云Token Plan团队版功能价格与省钱购买指南

阿里云百炼近期推出了名为“Token Plan 团队版”的全新服务,这一服务专为企业与开发者量身打造,定位为AI大模型订阅平台。通过引入Credits作为统一计量单位,将文本生成、图像生成等多模态AI能力纳入单一计费体系,同时无缝兼容主流AI编程工具及智能体(Agent)生态系统。其核心亮点包括:全

阿里云物联网.NET Core客户端位置信息上报
AI教程 · 2026-06-29

阿里云物联网.NET Core客户端位置信息上报

阿里云物联网平台的位置服务并非一个完全独立的功能模块。位置信息可包含二维坐标与三维坐标,而位置数据的来源本质上是借助设备属性进行上传。换言之,若要让设备上报位置,您需先将其视为一个普通属性进行处理。 1)添加二维位置数据 操作过程十分简洁。进入数据分析 → 空间数据可视化 → 二维数据,点击添加,将

年阿里云服务器选型配置与网站部署全攻略
AI教程 · 2026-06-29

年阿里云服务器选型配置与网站部署全攻略

2026年,阿里云服务器生态已高度成熟,形成了清晰的轻量应用服务器与ECS云服务器两大产品阵营。无论你是计划搭建个人博客、企业官网,还是运营电商平台、进行应用开发,基本都能找到理想的解决方案。本指南将从服务器选型、配置选择、部署流程到安全运维,系统梳理2026年最实用的操作要点,帮助你少走弯路,让网