范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

一文详解四种经典限流算法,面试必备

  前言
  最近一位朋友去拼夕夕面试,被问了这么一道题:限流算法有哪些?用代码实现令牌桶算法。跟好友讨论了一波,发现大家都忘记得差不多了.所以再整理一波,常见的四种限流算法,以及简单代码实现,相信大家看完,会茅塞顿开的。
  1. 固定窗口限流算法1.1 什么是固定窗口限流算法
  固定窗口限流算法(Fixed Window Rate Limiting Algorithm)是一种最简单的限流算法,其原理是在固定时间窗口(单位时间)内限制请求的数量。该算法将时间分成固定的窗口,并在每个窗口内限制请求的数量。具体来说,算法将请求按照时间顺序放入时间窗口中,并计算该时间窗口内的请求数量,如果请求数量超出了限制,则拒绝该请求。
  假设单位时间(固定时间窗口)是1秒,限流阀值为3。在单位时间1秒内,每来一个请求,计数器就加1,如果计数器累加的次数超过限流阀值3,后续的请求全部拒绝。等到1s结束后,计数器清0,重新开始计数。如下图:
  1.2 固定窗口限流的伪代码实现   public static Integer counter = 0;  //统计请求数    public static long lastAcquireTime =  0L;    public static final Long windowUnit = 1000L ; //假设固定时间窗口是1000ms    public static final Integer threshold = 10; // 窗口阀值是10         /**      * 固定窗口时间算法      * 关注公众号:捡田螺的小男孩      * @return      */     public synchronized boolean fixedWindowsTryAcquire() {         long currentTime = System.currentTimeMillis();  //获取系统当前时间         if (currentTime - lastAcquireTime > windowUnit) {  //检查是否在时间窗口内             counter = 0;  // 计数器清0             lastAcquireTime = currentTime;  //开启新的时间窗口         }         if (counter < threshold) {  // 小于阀值             counter++;  //计数统计器加1             return true;         }          return false;     } 复制代码1.2 固定窗口算法的优缺点优点:固定窗口算法非常简单,易于实现和理解。缺点:存在明显的临界问题,比如: 假设限流阀值为5个请求,单位时间窗口是1s,如果我们在单位时间内的前0.8-1s和1-1.2s,分别并发5个请求。虽然都没有超过阀值,但是如果算0.8-1.2s,则并发数高达10,已经超过单位时间1s不超过5阀值的定义啦。
  2. 滑动窗口限流算法2.1 什么是滑动窗口限流算法
  滑动窗口限流算法是一种常用的限流算法,用于控制系统对外提供服务的速率,防止系统被过多的请求压垮。它将单位时间周期分为n个小周期,分别记录每个小周期内接口的访问次数,并且根据时间滑动删除过期的小周期。它可以解决固定窗口临界值的问题。
  用一张图解释滑动窗口算法,如下:
  假设单位时间还是1s,滑动窗口算法把它划分为5个小周期,也就是滑动窗口(单位时间)被划分为5个小格子。每格表示0.2s。每过0.2s,时间窗口就会往右滑动一格。然后呢,每个小周期,都有自己独立的计数器,如果请求是0.83s到达的,0.8~1.0s对应的计数器就会加1。
  我们来看下,滑动窗口,去解决固定窗口限流算法的临界问题,思想是怎样
  假设我们1s内的限流阀值还是5个请求,0.8~1.0s内(比如0.9s的时候)来了5个请求,落在黄色格子里。时间过了1.0s这个点之后,又来5个请求,落在紫色格子里。如果是固定窗口算法,是不会被限流的,但是滑动窗口的话,每过一个小周期,它会右移一个小格。过了1.0s这个点后,会右移一小格,当前的单位时间段是0.2~1.2s,这个区域的请求已经超过限定的5了,已触发限流啦,实际上,紫色格子的请求都被拒绝啦。
  当滑动窗口的格子周期划分的越多,那么滑动窗口的滚动就越平滑,限流的统计就会越精确。2.2 滑动窗口限流算法的伪代码实现 /**      * 单位时间划分的小周期(单位时间是1分钟,10s一个小格子窗口,一共6个格子)      */     private int SUB_CYCLE = 10;      /**      * 每分钟限流请求数      */     private int thresholdPerMin = 100;      /**      * 计数器, k-为当前窗口的开始时间值秒,value为当前窗口的计数      */     private final TreeMap counters = new TreeMap<>();     /**      * 滑动窗口时间算法实现      */      public synchronized boolean slidingWindowsTryAcquire() {         long currentWindowTime = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) / SUB_CYCLE * SUB_CYCLE; //获取当前时间在哪个小周期窗口         int currentWindowNum = countCurrentWindow(currentWindowTime); //当前窗口总请求数          //超过阀值限流         if (currentWindowNum >= thresholdPerMin) {             return false;         }          //计数器+1         counters.get(currentWindowTime)++;         return true;     }     /**     * 统计当前窗口的请求数     */     private synchronized int countCurrentWindow(long currentWindowTime) {         //计算窗口开始位置         long startTime = currentWindowTime - SUB_CYCLE* (60s/SUB_CYCLE-1);         int count = 0;          //遍历存储的计数器         Iterator> iterator = counters.entrySet().iterator();         while (iterator.hasNext()) {             Map.Entry entry = iterator.next();             // 删除无效过期的子窗口计数器             if (entry.getKey() < startTime) {                 iterator.remove();             } else {                 //累加当前窗口的所有计数器之和                 count =count + entry.getValue();             }         }         return count;     } 复制代码2.3 滑动窗口限流算法的优缺点
  优点:简单易懂精度高(通过调整时间窗口的大小来实现不同的限流效果)可扩展性强(可以非常容易地与其他限流算法结合使用)
  缺点:突发流量无法处理(无法应对短时间内的大量请求,但是一旦到达限流后,请求都会直接暴力被拒绝。酱紫我们会损失一部分请求,这其实对于产品来说,并不太友好),需要合理调整时间窗口大小。3. 漏桶限流算法3.1 什么是漏桶限流算法
  漏桶限流算法(Leaky Bucket Algorithm)是一种流量控制算法,用于控制流入网络的数据速率,以防止网络拥塞。它的思想是将数据包看作是水滴,漏桶看作是一个固定容量的水桶,数据包像水滴一样从桶的顶部流入桶中,并通过桶底的一个小孔以一定的速度流出,从而限制了数据包的流量。
  漏桶限流算法的基本工作原理是:对于每个到来的数据包,都将其加入到漏桶中,并检查漏桶中当前的水量是否超过了漏桶的容量。如果超过了容量,就将多余的数据包丢弃。如果漏桶中还有水,就以一定的速率从桶底输出数据包,保证输出的速率不超过预设的速率,从而达到限流的目的。
  流入的水滴,可以看作是访问系统的请求,这个流入速率是不确定的。桶的容量一般表示系统所能处理的请求数。如果桶的容量满了,就达到限流的阀值,就会丢弃水滴(拒绝请求)流出的水滴,是恒定过滤的,对应服务按照固定的速率处理请求。3.2 漏桶限流算法的伪代码实现 /**  * LeakyBucket 类表示一个漏桶,  * 包含了桶的容量和漏桶出水速率等参数,  * 以及当前桶中的水量和上次漏水时间戳等状态。  */ public class LeakyBucket {     private final long capacity;    // 桶的容量     private final long rate;        // 漏桶出水速率     private long water;             // 当前桶中的水量     private long lastLeakTimestamp; // 上次漏水时间戳      public LeakyBucket(long capacity, long rate) {         this.capacity = capacity;         this.rate = rate;         this.water = 0;         this.lastLeakTimestamp = System.currentTimeMillis();     }      /**      * tryConsume() 方法用于尝试向桶中放入一定量的水,如果桶中还有足够的空间,则返回 true,否则返回 false。      * @param waterRequested      * @return      */     public synchronized boolean tryConsume(long waterRequested) {         leak();         if (water + waterRequested <= capacity) {             water += waterRequested;             return true;         } else {             return false;         }     }      /**      * 。leak() 方法用于漏水,根据当前时间和上次漏水时间戳计算出应该漏出的水量,然后更新桶中的水量和漏水时间戳等状态。      */     private void leak() {         long now = System.currentTimeMillis();         long elapsedTime = now - lastLeakTimestamp;         long leakedWater = elapsedTime * rate / 1000;         if (leakedWater > 0) {             water = Math.max(0, water - leakedWater);             lastLeakTimestamp = now;         }     } }  复制代码注意: tryConsume() 和 leak() 方法中,都需要对桶的状态进行同步,以保证线程安全性。3.3 漏桶限流算法的优缺点
  优点可以平滑限制请求的处理速度,避免瞬间请求过多导致系统崩溃或者雪崩。可以控制请求的处理速度,使得系统可以适应不同的流量需求,避免过载或者过度闲置。可以通过调整桶的大小和漏出速率来满足不同的限流需求,可以灵活地适应不同的场景。
  缺点需要对请求进行缓存,会增加服务器的内存消耗。对于流量波动比较大的场景,需要较为灵活的参数配置才能达到较好的效果。但是面对突发流量的时候,漏桶算法还是循规蹈矩地处理请求,这不是我们想看到的啦。流量变突发时,我们肯定希望系统尽量快点处理请求,提升用户体验嘛。4. 令牌桶算法4.1 什么是令牌桶算法
  令牌桶算法是一种常用的限流算法,可以用于限制单位时间内请求的数量。该算法维护一个固定容量的令牌桶,每秒钟会向令牌桶中放入一定数量的令牌。当有请求到来时,如果令牌桶中有足够的令牌,则请求被允许通过并从令牌桶中消耗一个令牌,否则请求被拒绝。
  4.2 令牌桶算法的伪代码实现/**  * TokenBucket 类表示一个令牌桶  */ public class TokenBucket {      private final int capacity;     // 令牌桶容量     private final int rate;         // 令牌生成速率,单位:令牌/秒     private int tokens;             // 当前令牌数量     private long lastRefillTimestamp;  // 上次令牌生成时间戳      /**      * 构造函数中传入令牌桶的容量和令牌生成速率。      * @param capacity      * @param rate      */     public TokenBucket(int capacity, int rate) {         this.capacity = capacity;         this.rate = rate;         this.tokens = capacity;         this.lastRefillTimestamp = System.currentTimeMillis();     }      /**      * allowRequest() 方法表示一个请求是否允许通过,该方法使用 synchronized 关键字进行同步,以保证线程安全。      * @return      */     public synchronized boolean allowRequest() {         refill();         if (tokens > 0) {             tokens--;             return true;         } else {             return false;         }     }      /**      * refill() 方法用于生成令牌,其中计算令牌数量的逻辑是按照令牌生成速率每秒钟生成一定数量的令牌,      * tokens 变量表示当前令牌数量,      * lastRefillTimestamp 变量表示上次令牌生成的时间戳。      */     private void refill() {         long now = System.currentTimeMillis();         if (now > lastRefillTimestamp) {             int generatedTokens = (int) ((now - lastRefillTimestamp) / 1000 * rate);             tokens = Math.min(tokens + generatedTokens, capacity);             lastRefillTimestamp = now;         }     } } 复制代码4.3 令牌桶算法的优缺点
  优点:稳定性高:令牌桶算法可以控制请求的处理速度,可以使系统的负载变得稳定。精度高:令牌桶算法可以根据实际情况动态调整生成令牌的速率,可以实现较高精度的限流。弹性好:令牌桶算法可以处理突发流量,可以在短时间内提供更多的处理能力,以处理突发流量。
  Guava的RateLimiter限流组件,就是基于令牌桶算法实现的。
  缺点:实现复杂:相对于固定窗口算法等其他限流算法,令牌桶算法的实现较为复杂。 对短时请求难以处理:在短时间内有大量请求到来时,可能会导致令牌桶中的令牌被快速消耗完,从而限流。这种情况下,可以考虑使用漏桶算法。时间精度要求高:令牌桶算法需要在固定的时间间隔内生成令牌,因此要求时间精度较高,如果系统时间不准确,可能会导致限流效果不理想。
  总体来说,令牌桶算法具有较高的稳定性和精度,但实现相对复杂,适用于对稳定性和精度要求较高的场景。

螃蟹虽香,但这4类人不能多吃大家好,我是中医张玉琴,今天和大家说说关于吃螃蟹的事,建议大家在看之前啊,先点赞收藏,免得等下找不到了!秋风起,蟹脚肥,中秋刚过,不知道大家的饭桌上有没有这样一道菜啊?那就是螃蟹,医生很少提及的天麻醒脑胶囊,不止滋补肝肾,还能治5种病大家好,我是和医生,今天给大家分享一个很不起眼的中成药,医生也很少提及它,今天我给大家讲一讲,它不止可以滋补肝肾,疏经活络,并且还可以调理5种病,建议点赞收藏!在此之前呢,先简单带中国金花绝境爆发!2比4后轰4比0,淘汰美网四强名将,兴奋怒吼作为中国金花前一姐,王蔷打出了一场个人标志性的比赛,首盘4比0大幅领先的情况下一度崩盘,虽然拼下首盘,但依然没顶住对手的疯狂反扑,被拖入决胜盘。第3盘,她在2比4落后的情况下绝境爆安吉透露爵士交易真因!队员之间互不信任,未来两年选秀质量更高北京时间9月13日,爵士队召开新闻发布会,CEO丹尼安吉和总经理扎尼克谈到爵士要进行大交易的原因。此前他们1换10送走戈贝尔,1换8送走了米切尔,还和湖人进行交易,送走贝弗利。我在邓亚萍一家三口近况!16岁儿子打球天赋高,因国籍问题备受质疑近日,不少乒乓球球迷都在关注成都团体世乒赛的举办情况,在北京时间9月11日的时候,国乒正式公布了世乒赛的参赛名单,随着陈幸同拿到阿曼挑战赛的冠军,她将自动获得第5人的资格,虽然小将罚款禁赛!NBA官方介入调查!状元郎这次真的玩大了北京时间9月13日,根据森林狼记者ChrisHine报道,NBA正在对球员爱德华兹社交媒体上发表的言论进行审查,他很有可能会面临罚款和禁赛的处理!状元郎这次真的玩大了事情是这样的,威少拒绝买断!湖人难觅交易第三方,安吉透露爵士交易双核真因虽然森林狼后卫爱德华兹已经为自己在个人社交媒体上发布恐同视频而道歉,但仍然遭来如潮水般的指责与谩骂,森林狼官方不得不对此做出回应,对爱德华兹个人所给同性恋群体造成的冒犯感到抱歉。虽ATP官宣!中国网球创新高,四大满贯官方盛赞大爆发,历史首次ATP官网更新了最新一期排名,张之臻创造中国大陆男子网球新高,世界排名第122位!刚刚结束的美网,中国网球整体表现出色,四大满贯官方如今回顾和盛赞了中国选手的表现。如今ATP最新世宜建立自主可控的车用芯片和操作系统技术体系万物互联时代,操作系统的边界在不断突破,面向人机物融合的泛在计算场景,能够支撑分布式人机物协同应用的操作系统将是产业未来之光。操作系统在经过主机时代PC互联时代移动互联时代之后,来李易峰塌房后,竟上线打了几把游戏,但上线时间暴露了他的焦虑这个中秋节假期,很多人没办法出门旅游,但应该也过得不无聊吧?李易峰的瓜,让很多人度过了这3天假期。先是被爆料塌房,然后李易峰发声明,结果被官方实锤,这一巴掌打的,真的是要多疼有多疼以光为刀!之江实验室研发出新装备将推动光子芯片等器件研发视频加载中9月上旬,之江实验室举行了成立以来最大规模的集中科研成果发布会,面向公众重磅发布了十余项科研成果,高通量激光直写光刻技术与装备就是其中之一。以光为刀,在特殊材料上雕刻出设
辟谣!喝完白酒透一透真的有用吗?心理安慰还是真有道理?很多酒友在宿醉之后醒来,都会再喝上两口,感觉这样会减轻宿醉,这种做法常被大家称为透一透,也有酒友称之为回魂酒。这样的做法在很多人看来都是无法理解的,甚至会觉得匪夷所思,本来喝醉都已汤逊湖边漫说茶(一)绿茶的功效冲泡及挑选绿茶是中国七大茶类之一,也是我国产量最大的茶品。十大名茶中,有六种是绿茶。绿茶的功效绿茶富含茶多酚儿茶素叶绿素咖啡碱氨基酸维生素等营养成分,具有多种功效与作用,经常喝绿茶有利于身体湿气除,百病无,中医教你分辨湿寒,湿热,痰湿,暑湿祛除一身湿大家好,我是沈医生,中医认为湿生百病,现在大多人身上都存在湿气,想要祛湿,但湿气可藏于各个脏腑,还可夹杂其他病邪形成湿寒,湿热,痰湿等情况,那该如何有效除湿呢?今天我就来教大家正确又增8种!新版致癌物清单发布,其中7种与食物有关,第1种你可能天天碰从不吸烟很少饮酒,生活中甚至没有什么坏习惯的人,突然被确诊了癌症,这是很多人无法接受,却也一直在发生的噩耗。实际上,不止饮食,很多致癌因素就藏在我们日常生活中,让人防不胜防。因此,明日小雪,中老年人牢记3宜3忌,养阳护阴,阳气足体质佳明日,二十四节气中的小雪节气便如约而至。此时天气渐渐寒冷,降水形式开始由雨变为雪,但还未到严冬漫天飞雪之时,故称其为小雪。小雪过后,万物都开始冬藏,一时间草木枯萎,万物沉寂,冬日已冬季容易咽干上火?喝它利咽润肺又润肠最近有圈友给我们发来留言说自己一到冬季就感觉咽干上火声音嘶哑听说用罗汉果泡水喝可以缓解?这种说法对吗?怎么用罗汉果泡水效果更好呢?詹志来中国中医科学院中药资源中心研究员罗汉果都有哪聊中药牡丹皮唯有牡丹真国色,开花时节动京城,牡丹花的美丽世人皆知,自古以来就是大富大贵的象征,具有很高的观赏价值。而牡丹的根皮凉血而不留瘀,活血而不妄行,是一味上佳的中药。牡丹皮的命名与其种植刘强东套现640亿携孕妻远走美国,老家祖宅被泼油漆自明州事件爆发后,刘强东已接连从300余家京东系企业抽身,近日又被曝出转让京东健康京东物流两员京东系大将45的股份。与此同时,他还被拍到携孕妻章泽天现身美国。48岁的他,身上似乎再92基金经理押注美国明年将出现滞胀!花旗称软着陆无法实现智通财经APP获悉,近期美国低于预期的通胀数据表明,美联储最终或许能够实现软着陆。但这种观点在大型基金经理中并不普遍,美国银行一项最新的基金经理调查显示,高达92的受访者押注美国明泰山第三门将交学费!郝伟搏命三中锋仍没能拿分让出争冠主动权客场12不敌成都蓉城,山东泰山终结了五连胜的脚步,积分榜跌回第二位。纵观整场比赛,在王大雷停赛韩镕泽受伤的情况下,第三门将李冠希为年轻交了学费,两个失球都与他的判断站位失误有关。此一小时内吃完,奖励100美金,美国一面馆放话,还没有人成功中国的面食不管是南方还是北方,都是比较受人喜欢的。特别是北方的面食,吃的种类是比较多的,而且做的花样也多。比如说西安的各种面,浆水鱼鱼,臊子面,油泼面,面皮还分热的和冷的等等,各种