`

大型网站限流算法的实现和改造

阅读更多

最近写了一个限流的插件,所以避免不了的接触到了一些限流算法。本篇文章就来分析一下这几种常见的限流算法

分析之前

  1. 依我个人的理解来说限流的话应该灵活到可以针对每一个接口来做。比如说一个类里面有5个接口,那么我的限流插件就应该能针对每一个接口就行不同的限流方案。所以呢,既然针对的每个接口所以就需要一个可以唯一标示这个接口的key(我取的是类名+方法名+入参)。
  2. 分布式限流强烈推荐使用redis+lua或者nginx+lua来实现。
  3. 这里用2个限流条件来做示例讲一下常见的限流算法:
    1. 接口1它10秒钟最大允许访问100次
    2. 接口2它10秒钟最大允许每个人访问100次。

计数器算法

这个算法可以说是限流算法中最简单的一种算法了。

核心思想

计数器算法的意思呢就是当接口在一个时间单位中被访问时,我就记下来访问次数,直到它访问的次数到达上限。

涉及变量
  1. 接口(key)
  2. 时间单位(expire)
  3. 允许访问多少次(limit)
  4. 访问次数(value)
条件一

当一个请求过来时,我们就会得到这个key。

1
2
3
4
5
6
7
8
9
if(存在key){
   value++;
   if(value>=limit){
   		不能访问
   	}
   }else{
   	添加key,value为1
       设置key过期时间为expire
   }
条件二

既然条件一已经实现了,那条件二会复杂么 ?

相比于条件一来说就是同一个key对应了多个用户。那么我们只需要把key加上用户的信息就可以了。比如说 key_用户1、key_用户2。

漏桶算法

核心思想

漏桶算法的意思呢就是一个接口在一个时间单位中允许被访问次数是动态变化的(假如一分钟允许访问60次,那么从开始计时时不管有没有被访问第59秒只允许访问59次,30秒只允许30次)。为什么这样呢,因为有另外一个线程在进行递减操作

涉及变量
  1. 接口(key)
  2. 时间单位(expire)
  3. 允许访问多少次(limit)
  4. 递减间隔时间(interval)
  5. 递减步长(step)
  6. 剩余可访问次数(value)
  7. key的访问时间(lastUpdateTime)
  8. 当前时间(nowTime)(注意nowTime的取值应为应用取得的时间而不是redis或者nginx取得的时间)
条件一

线程一:

1
2
3
4
5
6
7
8
if(存在key){
   value--;
   if(value<=0){
   		不能访问
   	}
   }else{
   	添加key,设置value为limit
   }

线程二:

1
2
3
while(过去interval时间){
   所有key的value-step
   }
条件二

参考计数器算法条件二实现。

算法升级

可以看到实现漏桶算法的话需要每隔interval时间都要另外一条线程去遍历所key的value去做递减操作,那么有没有什么办法可以省略这一步呢。答案是肯定有。

1
2
3
4
5
6
7
8
9
10
11
12
13
if(存在key){
   value--;
   if((nowTime-lastUpdateTime)>interval){
   	value=value-(nowTime-lastUpdateTime)/interval*step;
       lastUpdateTime=nowTime;
   }
   if(value<=0){
   		不能访问
   	}
   }else{
   	添加key,设置value为limit;
       lastUpdateTime=nowTime;
   }

令牌桶算法

核心思想

令牌桶算法呢,恰恰是和漏桶算法相反的一个算法,不过还是推荐你使用这个。这个算法的原理我不讲,我觉得聪明的你看了伪代码就明白了。

涉及变量
  1. 接口(key)
  2. 时间单位(expire)
  3. 允许访问多少次(limit)
  4. 递增间隔时间(interval)
  5. 递增步长(step)
  6. 当前可访问次数(value)
  7. key的访问时间(lastUpdateTime)
  8. 当前时间(nowTime)(参照漏桶算法需要注意的点)
条件一

线程一:

1
2
3
4
5
6
7
8
if(存在key){
   value++;
   if(value>=limit){
   		不能访问
   	}
   }else{
   	添加key,设置value为limit
   }

线程二:

1
2
3
while(过去interval时间){
   所有key的value+step
   }
条件二

参考计算器算法条件二实现。

算法升级

参考漏桶算法升级实现。

代码

代码实现请参考我的限流框架https://github.com/shiyujun/syj-ratelimit

 

 

 

推荐阅读

  1. SpringCloud学习系列汇总
  2. 为什么一线大厂面试必问redis,有啥好问的?
  3. 多线程面试必备基础知识汇总
  4. Java集合源码分析汇总-JDK1.8
  5. Linux常用命令速查-汇总篇
  6. JVM系列文章汇总

博客所有文章首发于公众号《Java学习录》转载请保留
扫码关注公众号即可领取2000GJava学习资源

1

1
0
分享到:
评论

相关推荐

    基于令牌桶算法的Java限流实现

    基于令牌桶算法的Java限流实现 在软件系统中,限流机制是一个重要的环节,它可以防止系统资源被过度使用,避免系统崩溃或性能下降。常见的限流算法有多种,如漏桶算法、令牌桶算法、滑动窗口算法等。在Java中,我们...

    限流算法分析与应用及源码.doc

    源码实现方面,限流算法的实现通常涉及数据结构(如队列、堆等)和并发控制(如锁、信号量等)。例如,使用Java的RateLimiter类(来自Guava库)可以轻松实现令牌桶算法。在设计限流模块时,还需要考虑线程安全、性能...

    常用4种限流算法介绍及比较.pdf

    例如,计数器算法和滑动窗口算法在单机和分布式环境下实现都很简单,但是滑动窗口算法由于更细的窗口划分,能够更好地应对周期性流量激增的问题。漏桶算法和令牌桶算法则需要更多的数据结构来存储和管理状态,但它们...

    基于令牌桶算法实现的SpringBoot无锁限流插件

    在本文中,我们将详细探讨如何利用令牌桶算法实现一个SpringBoot无锁限流插件,以及其在Java Web开发中的应用。 首先,SpringBoot作为一款轻量级的Java Web框架,因其简洁的配置和强大的功能深受开发者喜爱。结合...

    redis限流算法.zip

    在这个“redis限流算法.zip”压缩包中,我们能看到几个关键的限流算法实现,包括计数法、令牌桶算法,以及基于Redis的漏斗算法的思路。这些算法在高并发场景下尤其重要,能够防止系统过载,保持服务的稳定性和可靠性...

    基于并行免疫粒子群算法的限流措施优化.pdf

    为了提高优化效果,研究者们不断探索新的算法和方法。在这一过程中,基于群体智能的优化技术——粒子群优化算法(Particle Swarm Optimization, PSO)逐渐进入研究者的视野。PSO算法模拟鸟群捕食行为,通过粒子间的...

    限流的概念,算法,分布式限流以及微服务架构下限流的难点 - 知乎.pdf

    在分布式系统中实现限流,系统架构师和开发者必须深思熟虑,从服务端、客户端到网关的各个层次综合考虑限流方案。这涉及到充分理解业务特征,对系统进行性能压测,分析不同服务的资源消耗,以及在系统设计时预留资源...

    java实现限流,封装的工具类

    常见的限流算法有两种:令牌桶算法和漏桶算法。 1. **令牌桶算法**:令牌桶算法允许突发流量,但同时设置了最大速率。系统会按照一定的速率往桶里添加令牌,只有当桶中有令牌时,请求才能被处理。令牌的数量决定了...

    Java限流实现

    其中,令牌桶算法和漏桶算法在实际应用中更为常见,它们通过控制流入和流出速率来实现限流。 1. **令牌桶算法**:系统以恒定的速度生成令牌放入桶中,请求需要消耗令牌才能执行,当桶中没有令牌时,请求会被拒绝或...

    SpringBoot如何使用AOP+Redis实现接口限流实现全过程(值得珍藏)

    总结:通过 Spring Boot 结合 AOP 和 Redis,我们可以轻松实现接口限流,保护系统免受过量请求的影响。这种方式既灵活又高效,能够适应各种不同的限流需求。在实践中,根据实际情况调整限流策略,结合监控工具,可以...

    密码学实验之流密码算法:A5算法与RC4算法加密流程和python代码实现

    本文主要探讨了两种流密码算法——A5算法和RC4算法,以及它们在Python中的实现。 A5算法是GSM移动通信系统中用于语音通信加密的流密码。它的核心在于使用三个线性反馈移位寄存器(LFSR),通过初始状态和密钥生成...

    Go-RateLimiter基于TokenBucket算法实现的api限流模块

    本篇文章将深入探讨Go语言中基于Token Bucket算法实现的RateLimiter模块,这是一款用于API接口限流的工具。 首先,让我们理解什么是Token Bucket算法。Token Bucket是一种流量整形和速率限制算法,其核心思想是系统...

    最大流算法C语言实现

    最大流算法主要有两种经典的实现方法:Ford-Fulkerson算法和Edmonds-Karp算法。Ford-Fulkerson算法基于增广路径的概念,不断地寻找从源点到汇点的增广路径并更新流的值,直到找不到这样的路径为止。而Edmonds-Karp算...

    社区划分算法的python3实现, 包括KL算法、 COPAR、Louvain 算法、LFM算法、InfoMap算法等

    社区发现是网络分析中的一个重要领域,它旨在将网络中的节点划分为不同的群组或社区,以便更好...Python3的实现使得这些复杂的算法可以方便地集成到数据分析和可视化的工作流程中,为研究者和开发者提供了强大的工具。

    AES-GCM算法实现code

    主要是aes-gcm算法实现的code,详细描述gcm算法的各部分实现过程

    模型算法大全(20+种常用算法模型+代码实现)

    模型算法大全(20+种常用算法模型+代码实现)模型算法大全(20+种常用算法模型+代码实现)模型算法大全(20+种常用算法模型+代码实现)模型算法大全(20+种常用算法模型+代码实现)模型算法大全(20+种常用算法模型+...

    zuc算法的C语言实现

    ZUC算法的C语言实现,可修改需要的密钥流数量。最基本的算法实现,无附加。

    最大流的Dinic算法与SAP算法的实现

    对于实现这些算法,"NetworkFlow"这个压缩包文件可能包含了相关的代码示例或教程,可能包括Dinic算法和SAP算法的C++、Python或其他编程语言的实现。这些代码通常会定义图的数据结构,如节点和边,以及相关的操作函数...

    几个推荐算法的java实现

    总的来说,这个项目提供了多种推荐算法的Java实现,对于学习和应用推荐系统,尤其是对Java编程感兴趣的开发者,是非常有价值的资源。通过理解和实践这些算法,不仅可以提升对推荐系统的理解,也有助于提高解决实际...

Global site tag (gtag.js) - Google Analytics