最近写了一个限流的插件,所以避免不了的接触到了一些限流算法。本篇文章就来分析一下这几种常见的限流算法
分析之前
- 依我个人的理解来说限流的话应该灵活到可以针对每一个接口来做。比如说一个类里面有5个接口,那么我的限流插件就应该能针对每一个接口就行不同的限流方案。所以呢,既然针对的每个接口所以就需要一个可以唯一标示这个接口的key(我取的是类名+方法名+入参)。
- 分布式限流强烈推荐使用redis+lua或者nginx+lua来实现。
- 这里用2个限流条件来做示例讲一下常见的限流算法:
- 接口1它10秒钟最大允许访问100次
- 接口2它10秒钟最大允许每个人访问100次。
计数器算法
这个算法可以说是限流算法中最简单的一种算法了。
核心思想
计数器算法的意思呢就是当接口在一个时间单位中被访问时,我就记下来访问次数,直到它访问的次数到达上限。
涉及变量
- 接口(key)
- 时间单位(expire)
- 允许访问多少次(limit)
- 访问次数(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次)。为什么这样呢,因为有另外一个线程在进行递减操作
涉及变量
- 接口(key)
- 时间单位(expire)
- 允许访问多少次(limit)
- 递减间隔时间(interval)
- 递减步长(step)
- 剩余可访问次数(value)
- key的访问时间(lastUpdateTime)
- 当前时间(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; } |
令牌桶算法
核心思想
令牌桶算法呢,恰恰是和漏桶算法相反的一个算法,不过还是推荐你使用这个。这个算法的原理我不讲,我觉得聪明的你看了伪代码就明白了。
涉及变量
- 接口(key)
- 时间单位(expire)
- 允许访问多少次(limit)
- 递增间隔时间(interval)
- 递增步长(step)
- 当前可访问次数(value)
- key的访问时间(lastUpdateTime)
- 当前时间(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
推荐阅读
- SpringCloud学习系列汇总
- 为什么一线大厂面试必问redis,有啥好问的?
- 多线程面试必备基础知识汇总
- Java集合源码分析汇总-JDK1.8
- Linux常用命令速查-汇总篇
- JVM系列文章汇总
博客所有文章首发于公众号《Java学习录》转载请保留
扫码关注公众号即可领取2000GJava学习资源
相关推荐
6、 操作系统是一个大型的程序系统,它负责计算机的全部软、硬件资源的分配、调度工作,控制并协调并发活动,实现信息的存取和保护。它提供用户接口,使用户获得良好的工作环境。操作系统使整个计算机系统实现了高...
在FPGA上实现CNN加速器的设计和优化涉及到多个层面的考虑,包括并行处理策略、数据流管理、资源分配和调度等。块卷积方法在其中起到了关键作用,不仅减少了内存使用,还可能通过减少数据传输来提高计算单元的利用率...
高并发下的服务降级、限流实战 基于分布式架构下分布式锁的解决方案实战 分布式架构实现分布式定时调度 分布式架构-中间件 分布式消息通信 消息中间件在分布式架构中的应用 ActiveMQ ActiveMQ高可用集群企业...
7. **流量管理**:包括API网关、限流、熔断等,保障系统的高可用性和稳定性。 **关键技术** 1. **服务网格**:通过ISTIO等服务网格技术,实现服务间的无侵入治理,简化微服务的管理和调用。 2. **容器编排**:...
说明:数据仓库是用来存储历史数据的大型数据库,以便进行数据分析和支持决策。XML(可扩展标记语言)是一种广泛使用的数据交换格式,特别是在Web服务中。 3. **工作流技术** 工作流技术用于自动化业务流程管理,...
- **降级与限流**:保护系统免受异常流量冲击。 - **负载均衡**:合理分配请求至各个服务实例。 #### 三、第一代服务框架的设计与挑战 京东的第一代服务框架于2012年开始研发,基于开源的服务框架构建,并采用了...
- **过载保护**: 设计合理的限流措施防止服务器过载。 **8. LVS为何不能完全替代DNS轮询** - **比较**: LVS是一种基于Linux内核的虚拟服务器解决方案。 - **局限性**: 在动态调整服务器权重方面不如DNS灵活。 - **...
其主要目的是在满足所有设备限制(如线路热限、变压器容量、发电机出力等)的前提下,找出系统在特定负荷条件下的稳定运行点。这一过程通常包括以下几个步骤: 1. **建立模型**:根据电力网络结构和设备参数,构建...
2. **社区检测算法优化**:可能涉及将传统的社区检测算法(如Louvain、Label Propagation、Greedy Modularity Maximization等)进行GPU并行化改造的过程,以及优化策略。 3. **CUDA编程基础**:简要介绍CUDA编程的...
- **方案设计:**结合物联网技术和人工智能算法,构建智能化的安防管理体系。 - **方案特色:**支持实时预警、智能识别等功能,提高安全防范水平。 - **智慧决策智能调度平台:** - 通过大数据分析技术,实现...