当前位置: 首页 > news >正文

滑动时间窗口实现重试限流

滑动时间窗口实现重试限流,有效避免在短时间内大量请求失败导致的重试风暴问题。

class SlidingWindow {private List<RequestRecord> window = new ArrayList<>();private int threshold; // 超时阈值private int windowSize; // 窗口大小private long windowDuration; // 窗口时间范围(毫秒)public SlidingWindow(int threshold, int windowSize, long windowDuration) {this.threshold = threshold;this.windowSize = windowSize;this.windowDuration = windowDuration;}synchronized void add(RequestRecord req) {// 移除过期的请求记录long currentTime = System.currentTimeMillis();window.removeIf(r -> (currentTime - r.getTimestamp()) > windowDuration);// 如果窗口已满,移除最早的记录if (window.size() >= windowSize) {window.remove(0);}window.add(req);  // 添加请求记录}boolean allowRetry() {int timeoutCount = 0;long currentTime = System.currentTimeMillis();// 统计窗口内超时的失败请求for (RequestRecord r : window) {if (r.isTimeout() && !r.isSuccess() && (currentTime - r.getTimestamp()) <= windowDuration) {timeoutCount++;}}return timeoutCount < threshold;  // 判断是否允许重试}
}// 请求记录类
class RequestRecord {private long timestamp; // 请求时间戳private int timeoutThreshold; // 超时阈值(毫秒)private boolean success; // 请求是否成功public RequestRecord(long timestamp, int timeoutThreshold, boolean success) {this.timestamp = timestamp;this.timeoutThreshold = timeoutThreshold;this.success = success;}public boolean isTimeout() {long currentTime = System.currentTimeMillis();return (currentTime - timestamp) > timeoutThreshold; // 判断是否超时的逻辑}public long getTimestamp() {return timestamp;}public boolean isSuccess() {return success;}
}public class OrderController {public static void main(String[] args) {// 初始化滑动窗口,设置超时阈值为3,窗口大小为10,时间窗口为1分钟SlidingWindow slidingWindow = new SlidingWindow(3, 10, 60000);// 模拟请求和重试逻辑for (int i = 0; i < 15; i++) {try {Thread.sleep(200);} catch (InterruptedException e) {throw new RuntimeException(e);}boolean success = Math.random() > 0.5; // 随机模拟请求成功或失败RequestRecord record = new RequestRecord(System.currentTimeMillis(), 150, success);slidingWindow.add(record);if (!success && slidingWindow.allowRetry()) {System.out.println("请求失败,触发重试");} else if (!success) {System.out.println("请求失败,达到重试阈值,不再重试");} else {System.out.println("请求成功");}}}
}

局限性:

• 内存爆炸:每秒数万次请求需存储数万条记录,内存占用高达40MB(10万QPS场景)。

• 遍历开销:每次判定需遍历全部请求,时间复杂度为O(n),导致CPU峰值负载达70-90%。

• 锁竞争严重:多线程更新窗口需加锁,吞吐量仅5,000 QPS。

相关文章:

  • 解决模拟器打开小红书设备异常问题
  • SpringBoot入门实战(第一篇:环境准备和项目初始化)
  • 深度可分离卷积与普通卷积的区别及原理
  • 【数据库】事务
  • 深入剖析Java并发编程原理:从底层到实践
  • C++move的作用和原理
  • LeetCode每日一题4.20
  • 模拟实现memmove,memcpy,memset
  • iPhone 13P 换超容电池,一年实记的“电池循环次数-容量“柱状图
  • ebpf: CO-RE, BTF, and Libbpf(三)
  • 标准的JNI (Java Native Interface) 加载函数 JNI_OnLoad
  • VLC搭建本机的rtsp直播推流和拉流
  • 如何成为Agent工程师:学习路径、核心技能与职业规划
  • 深入剖析 MySQL 中用户授权机制及操作
  • 指针(3)
  • 【上位机——MFC】MFC入门
  • day 22 作业
  • 实战指南:封装Faster-Whisper为FastAPI接口并实现高并发处理-附整合包
  • SAP PO开发-端到端配置
  • 2.1 基于委托的异步编程方法
  • 上海农房翻建为何难?基层盼政策适度松动
  • 魔都眼|上海半马鸣枪:白金标运动员、“箱根之子”齐参赛
  • 龙登高谈近世的基层治理及制度变迁
  • 在没有穹顶的剧院,和春天的音乐会来一场约会
  • 亚太峰会上哪个词最火?我们问了问AI
  • 浙江金华一副镇长被指殴打村民,镇党委称仍在调查核实