点击上方蓝色“程序猿DD”,选择“设为星标”

回复“资源”获取独家整理的学习资料!

作者 | dijia478

来源 | https://www.cnblogs.com/dijia478/p/13807826.html

在网上搜滑动时间窗口限流算法,大多都太复杂了,本人实现了个简单的,先上代码:

package cn.dijia478.util;import java.time.LocalTime;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;/*** 滑动时间窗口限流工具* 本限流工具只适用于单机版,如果想要做全局限流,可以按本程序的思想,用redis的List结构去实现** @author dijia478* @date 2020-10-13 10:53*/
public class SlideWindow {/** 队列id和队列的映射关系,队列里面存储的是每一次通过时候的时间戳,这样可以使得程序里有多个限流队列 */private volatile static Map<String, List<Long>> MAP = new ConcurrentHashMap<>();private SlideWindow() {}public static void main(String[] args) throws InterruptedException {while (true) {// 任意10秒内,只允许2次通过System.out.println(LocalTime.now().toString() + SlideWindow.isGo("ListId", 2, 10000L));// 睡眠0-10秒Thread.sleep(1000 * new Random().nextInt(10));}}/*** 滑动时间窗口限流算法* 在指定时间窗口,指定限制次数内,是否允许通过** @param listId     队列id* @param count      限制次数* @param timeWindow 时间窗口大小* @return 是否允许通过*/public static synchronized boolean isGo(String listId, int count, long timeWindow) {// 获取当前时间long nowTime = System.currentTimeMillis();// 根据队列id,取出对应的限流队列,若没有则创建List<Long> list = MAP.computeIfAbsent(listId, k -> new LinkedList<>());// 如果队列还没满,则允许通过,并添加当前时间戳到队列开始位置if (list.size() < count) {list.add(0, nowTime);return true;}// 队列已满(达到限制次数),则获取队列中最早添加的时间戳Long farTime = list.get(count - 1);// 用当前时间戳 减去 最早添加的时间戳if (nowTime - farTime <= timeWindow) {// 若结果小于等于timeWindow,则说明在timeWindow内,通过的次数大于count// 不允许通过return false;} else {// 若结果大于timeWindow,则说明在timeWindow内,通过的次数小于等于count// 允许通过,并删除最早添加的时间戳,将当前时间添加到队列开始位置list.remove(count - 1);list.add(0, nowTime);return true;}}}

运行可以看到,任意10秒内,通过的次数不超过2次。或者按照实现原理来说,任意通过2次内的时间差,都不超过10秒:

这里画图做说明,为什么这样可以做到滑动窗口限流,假设10秒内允许通过5次

1.这条线就是队列list,当第一个事件进来,队列大小是0,时间是第1秒:

2.因为size=0,小于5,都没有到限制的次数,完全不用考虑时间窗口,直接把这次事件的时间戳放到0的位置:

3.第2.8秒的时候,第二个事件来了。因为此时size=1,还是小于5,把这次事件的时间戳放到0的位置,原来第1秒来的事件时间戳会往后移动一格:

4.陆续的又来了3个事件,队列大小变成了5,先来的时间戳依次向后移动。此时,第6个事件来了,时间是第8秒:

5.因为size=5,不小于5,此时已经达到限制次数,以后都需要考虑时间窗口了。所以取出位置4的时间(离现在最远的时间),和第6个事件的时间戳做比较:

6.得到的差是7秒,小于时间窗口10秒,说明在10秒内,来的事件个数大于5了,所以本次不允许通过:

7.接下来即便来上100个事件,只要时间差小于等于10秒,都同上,拒绝通过:

8.第11.1秒,第101次事件过来了。因为size=5,不小于5,所以取出位置4的时间(离现在最远的时间),和第101个事件的时间戳做比较:

9.得到的差是10.1秒,大于时间窗口10秒,说明在10秒内,来的事件个数小于等于5了,所以本次允许通过:

10.删除位置4的时间(离现在最远的时间),把这次事件的时间戳放到0的位置,后面的时间戳依次向后移动:

往后再来其他事件,就是重复4-10的步骤,即可实现,在任意滑动时间窗口内,限制通过的次数

其本质思想是转换概念,将原本问题的确定时间大小,进行次数限制。转换成确定次数大小,进行时间限制。

DD自研的沪牌代拍业务,点击直达

【往期推荐】

GitHub 推出 2020 宇宙新功能:Dark Mode!从此深夜搞开源不再被亮瞎了!

2020-12-12

基于 Token 的多平台身份认证架构设计

2020-12-12

Google 鼓励的 13 条代码审查标准,建议收藏!

2020-12-11

据说电脑上可以刷朋友圈啦!又多了个上班摸鱼的途径?

2020-12-11

又一个智商税产品“路由器防辐射笼”,信号都没了,还能火爆全网...

2020-12-10

滴滴十大技术方向开源项目出炉!

2020-12-10

扫一扫,关注我

一起学习,一起进步

每周赠书,福利不断

深度内容

推荐加入

欢迎加入知识星球,一起探讨技术架构,交流技术人生。

加入方式,长按下方二维码:

已在知识星球更新如下:

素质二连,走一个

Java 实现滑动时间窗口限流算法,你见过吗?相关推荐

  1. Sentinel滑动时间窗限流算法原理及源码解析(上)

    文章目录 时间窗限流算法 滑动时间窗口 滑动时间窗口算法改进 滑动时间窗口源码解析 时间窗限流算法 10t到16t 10个请求 16t-20t 50个请求 20t-26t 60个请求 26t到30t ...

  2. Sentinel滑动时间窗限流算法

    Sentinel系列文章 Sentinel熔断限流器工作原理 Sentinel云原生K8S部署实战 Sentinel核心源码解析 时间窗限流算法 如图 10-20这个时间窗内请求数量是60小于阈值10 ...

  3. Redis(六)——限流算法:滑动时间窗口限流和漏斗限流

    本文主要总结自<redis深度历险> 限流的意义 限流一般是指在一个时间窗口内对某些操作请求的数量进行限制,比如一个论坛限制用户每秒钟只能发一个帖子,每秒钟只能回复5个帖子.限流可以保证系 ...

  4. Sentinel滑动时间窗限流算法原理及源码解析(中)

    文章目录 MetricBucket MetricEvent数据统计的维度 WindowWrap样本窗口实例 范型T为MetricBucket windowLengthInMs 样本窗口长度 windo ...

  5. Sentinel滑动时间窗限流算法原理及源码解析(下)

    文章目录 对统计数据如何使用 获取之前统计好的数据 对统计数据如何使用 流控快速失败 获取之前统计好的数据

  6. JAVA实现滑动时间窗口

    先上代码 package demo;import java.time.LocalTime; import java.util.LinkedList; import java.util.List; im ...

  7. java 下载限速_Java 文件下载限流算法

    在做文件下载功能时,为了避免下载功能将服务器的带宽打满,从而影响服务器的其他服务.我们可以设计一个限流器来限制下载的速率,从而限制下载服务所占用的带宽. 一.算法思路 定义一个数据块chunk(单位 ...

  8. 【限流02】限流算法实战篇 - 手撸一个单机版Http接口通用限流框架

    本文将从需求的背景.需求分析.框架设计.框架实现几个层面一步一步去实现一个单机版的Http接口通用限流框架. 一.限流框架分析 1.需求背景 微服务系统中,我们开发的接口可能会提供给很多不同的系统去调 ...

  9. 【限流01】限流算法理论篇

    微服务就是将复杂的大应用拆分成小的应用,这样做的好处是各个应用之间独立开发.测试.上线,互不影响.但是服务拆分之后,带来的问题也很多,我们需要保障微服务的正常运行,就需要进行服务治理.常用手段有:鉴权 ...

最新文章

  1. 微服务注册中心的选型和思考
  2. Flash Socket安全问题的全面解析 服务器端代码
  3. 亚马逊给创业者5条建议:开会杜绝PPT
  4. QML基础类型之quaternion
  5. 微信搜一搜在线检索技术演进复盘
  6. 计算机网络第6章(应用层)
  7. sqlplus登录缓慢的问题分析过程及解决小记
  8. oracle数据库选件,一句话为你解读Oracle数据库选件
  9. Squid服务器配置
  10. 什么是GC Roots
  11. 为什么DNN的SectionHead Control图片无法显示,也无法折叠
  12. 输出结果 配置_用单端仪表放大器实现全差分输出
  13. Delphi7 动态数组
  14. 按键控制c51单片机驱动unl2003控制步进电机正反转停止及程序调速-萌新入门
  15. 小米手机销量是乐视的几十倍,为什么雷军还要去跟贾跃亭打口水战?
  16. 写给还在迷茫中的朋友,一名6年程序员的工作感悟!!!
  17. Oracle数据库管理每周一例-第十七期 ADG
  18. 【笔记】html 图片映射 usemap(vue环境下、map、area、coords)
  19. 互联网日报 | 蔚来发布官方二手车业务;去哪儿2020年实现全年盈利;港交所正式换帅...
  20. 一个文科生的工程师之路

热门文章

  1. Asp.net Dynamic Data之三改变编辑和操作数据的现实方式
  2. Druid连接池一个设置引发的血案
  3. centos上用yum安装rar/unrar
  4. win10 纯净版安装 U盘制作
  5. golang time.After 超时使用理解
  6. 堆溢出DWORD SHOOT原理
  7. linux insmod命令参数及用法详解--linux加载模块命令
  8. AWS-CLI-V2-Install
  9. python无法打开excle_无法打开Excel fi
  10. 关于istringstream用法的一个坑