限流——漏桶算法和令牌桶算法的区别
文章目录
- 限流
- 漏桶算法
- 令牌桶算法
- 漏桶算法和令牌桶算法的区别
- 时间窗口
- 时间窗口和令牌桶优缺点
限流
在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流
- 缓存:缓存的目的是提升系统访问速度和增大系统处理能力
- 降级:当服务流量剧增,影响到核心流程的性能,需要暂时屏蔽掉一些功能,待高峰过去或问题解决后再重新打开,以此释放服务器资源以保证核心任务的正常运行。
- 限流:限流的目的是通过对并发访问或请求进行限速,或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务、或排队或等待、降级等处理
常用的限流算法有令牌桶和,漏桶,滑动窗口
漏桶算法
漏桶(Leaky Bucket) 算法思路简单,水(请求)先进入到漏桶中,漏桶以一定的速度出水(接口有响应速率),当水流速度过大直接溢出(访问频率超过接口响应频率),然后就拒绝请求,可以看出漏桶算法能强制限制数据的传输速率。
令牌桶算法
对于很多应用场景来说,除了要求能够限制数据的平均传输速率外,还要求允许某种程度的突发传输。这时候漏桶算法可能就不合适了,令牌桶算法更为适合。如图2所示,令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。
相关实现算法
参考链接:redis令牌桶实现
漏桶算法和令牌桶算法的区别
**漏桶算法的出水速度是恒定的,**那么意味着如果瞬时大流量的话,将有大部分请求被丢弃掉(也就是所谓的溢出)。漏桶算法通常可以用于限制访问外部接口的流量,保护其他人系统,比如我们请求银行接口,通常要限制并发数。
令牌桶算法生成令牌的速度是恒定的,而请求去拿令牌是没有速度限制的。这意味,面对瞬时大流量,该算法可以在短时间内请求拿到大量令牌,可以处理瞬时流量,而且拿令牌的过程并不是消耗很大的事情。令牌桶算法通常可以用于限制被访问的流量,保护自身系统。
时间窗口
时间窗口,就是以时间间隔维度,统计这个时间段内的数量,和设置的阈值比较,达到限流效果。
如何区分各个时间窗口?
可以将“当前的毫秒数/时间区间“”,那么同一个时间区间计算的结果都是一样的,可以将这个值作为key,用来区分各个时间段。
比如: 用"当前的毫秒数/1000",就表示每一秒,用"当前的毫秒数/5000",就表示每5秒。
测试每一秒:从结果可以发现,同一秒内的毫秒数值,计算后得到的结果是一样的,可以将这个结果作为统计交易的key,用来区分各个时间段。
测试每3秒:可以发现每3秒内的输出值,都是一样的。
再来看限流实现,用Redis + Lua
Lua本身就是一种编程语言,虽然redis 官方没有直接提供限流相应的API,但却支持了 Lua 脚本的功能,可以使用它实现复杂的令牌桶或漏桶算法,也是分布式系统中实现限流的主要方式之一。
相比Redis事务,Lua脚本的优点:
减少网络开销:使用Lua脚本,无需向Redis发送多次请求,执行一次即可,减少网络传输
原子操作:Redis将整个Lua脚本作为一个命令执行,原子,无需担心并发
复用:Lua脚本一旦执行,会永久保存 Redis 中,其他客户端可复用
local key = KEYS[1] --限流KEY(一秒一个)
local limit = tonumber(ARGV[1]) --限流大小
local current = tonumber(redis.call('get', key) or "0")
if current + 1 > limit then --如果超出限流大小redis.call("INCRBY", key,"1") -- 如果不需要统计真是访问量可以不加这行return 0
else --请求数+1,并设置2秒过期redis.call("INCRBY", key,"1")if tonumber(ARGV[2]) > -1 thenredis.call("expire", key,tonumber(ARGV[2])) --时间窗口最大时间后销毁键endreturn 1
end
lua脚本返回值比较奇怪,用java客户端接受返回值,只能使用Long,没有去深究。这个脚本只需要传入key(url+时间戳/预设时间窗口大小),便可以实现限流。
这里也贴下java中配套的工具类
package sinosoftgz.apiGateway.utils;import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.util.Assert;import java.util.Arrays;/*** Created by xujingfeng on 2017/3/13.* <p>* 基于redis lua脚本的线程安全的计数器限流方案* </p>*/
public class RedisRateLimiter {/*** 限流访问的url*/private String url;/*** 单位时间的大小,最大值为 Long.MAX_VALUE - 1,以秒为单位*/final Long timeUnit;/*** 单位时间窗口内允许的访问次数*/final Integer limit;/*** 需要传入一个lua script,莫名其妙redisTemplate返回值永远是个Long*/private RedisScript<Long> redisScript;private RedisTemplate redisTemplate;/*** 配置键是否会过期,* true:可以用来做接口流量统计,用定时器去删除* false:过期自动删除,时间窗口过小的话会导致键过多*/private boolean isDurable = false;public void setRedisScript(RedisScript<Long> redisScript) {this.redisScript = redisScript;}public void setRedisTemplate(RedisTemplate redisTemplate) {this.redisTemplate = redisTemplate;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public boolean isDurable() {return isDurable;}public void setDurable(boolean durable) {isDurable = durable;}public RedisRateLimiter(Integer limit, Long timeUnit) {this.timeUnit = timeUnit;Assert.isTrue(timeUnit < Long.MAX_VALUE - 1);this.limit = limit;}public RedisRateLimiter(Integer limit, Long timeUnit, boolean isDurable) {this(limit, timeUnit);this.isDurable = isDurable;}public boolean acquire() {return this.acquire(this.url);}public boolean acquire(String url) {StringBuffer key = new StringBuffer();key.append("rateLimiter").append(":").append(url).append(":").append(System.currentTimeMillis() / 1000 / timeUnit);// 这里System.currentTimeMillis() / 1000 / timeUnit就是一个时间窗口,比如 5秒 内处理10个请求,timeUnit=5,limit=10Integer expire = limit + 1;String convertExpire = isDurable ? "-1" : expire.toString();return redisTemplate.execute(redisScript, Arrays.asList(key.toString()), limit.toString(), convertExpire).equals(1l);}}
时间窗口和令牌桶优缺点
优点:时间窗口和令牌桶相比,这种算法不需要去等待令牌生成的时间,在新的时间窗口,可以立即处理大量的请求。
缺点:在一个窗口临界点的前后时间,比如时间窗口是1分钟,在59秒和1分01秒同时突发大量请求,刚好请求全部落在前后相隔很近的节点上,极端情况下可能会带来 2 倍的流量,系统可能承受不了这么大的突发性流量。
限流——漏桶算法和令牌桶算法的区别相关推荐
- 信号量与令牌桶_限流的4种方式令牌桶实战
限流的4种方式 正文 限流 限流是对某一时间窗口内的请求数进行限制,保持系统的可用性和稳定性,防止因流量暴增而导致的系统运行缓慢或宕机.常用的限流算法有令牌桶和和漏桶,而Google开源项目Guava ...
- 限流算法之漏桶算法、令牌桶算法
限流 每个API接口都是有访问上限的,当访问频率或者并发量超过其承受范围时候,我们就必须考虑限流来保证接口的可用性或者降级可用性.即接口也需要安装上保险丝,以防止非预期的请求对系统压力过大而引起的系统 ...
- 接口限流算法:漏桶算法amp;令牌桶算法
转载自 接口限流算法:漏桶算法&令牌桶算法 背景 每一个对外提供的API接口都是需要做流量控制的,不然会导致系统直接崩溃.很简单的例子,和保险丝的原理一样,如果用电符合超载就会烧断保险丝断掉电 ...
- 限流算法(漏桶算法、令牌桶算法)对比
限流算法(漏桶算法.令牌桶算法) 漏桶算法: 有个桶,比如最大能进2个单位的水(请求),桶底有个洞,每个单位的水都会在桶里待3秒后漏下去. 那么这个桶就可以同时处理2个单位的水. 如果进水太多,同一时 ...
- 令牌桶算法和漏桶算法python_限流之漏桶算法与令牌桶算法
在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流 缓存:缓存的目的是提升系统访问速度和增大系统处理容量 降级:降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降 ...
- 限流-漏桶算法、令牌桶算法
1.问题 系统的某个接口访问量突然激增,没多久接口崩溃,形成连锁反应,导致整个系统崩溃. 如何应对这种情况呢? 为我们的接口加上"保险丝",预防这种突发情况,接口压力过大,造成整个 ...
- 高并发系统限流-漏桶算法和令牌桶算法
参考: https://www.cnblogs.com/xuwc/p/9123078.html http://www.cnblogs.com/LBSer/p/4083131.html https:// ...
- 限流算法漏桶算法和令牌桶算法
1.场景 我们知道,硬件设备或是服务器之类的通信速率或是服务器的响应速率是有限制的,当瞬时大量通信量情况下需要对速率进行限制,否则可能会出现宕机等服务无法提供的故障. 两个比较常用的算法有令牌桶算法. ...
- 面试官:连漏桶算法和令牌桶算法都不知道吗?回去多看看书吧
锁屏面试题百日百刷,每个工作日坚持更新面试题.锁屏面试题app.小程序现已上线,官网地址:https://www.demosoftware.cc/#/introductionPage.已收录了每日更新 ...
最新文章
- json格式天气数据的获取,jsonp方式获取统计图数据
- linux下用phpize给PHP动态添加扩展
- SQL Server (MSSQLSERVER) 服务因 2148081668 服务性错误而停止。
- 【网络流】学习笔记:一次理解网络流!
- Spark _13_二次排序问题
- 分享5个冷门而超级实用的在线网站,大家赶紧来看看吧!
- 安卓linux交叉编译,Linux Ubuntu下用Android NDK 生成独立交叉编译链
- python数据分析_使用Python进行数据分析
- 蓝桥杯数字三角形java,蓝桥杯数字三角形(java)
- iText和flying saucer结合生成pdf--显示分页页码
- vue + vue-router +axios + element UI + PHP + CodeIgniter + Mysql 项目管理系统
- 2018山西中考计算机软件名称,2018年山西省中考试题
- html5怎么给视频加字幕,2018版本的pr如何给视频加字幕?
- 两个3G模块相互通信
- java计算机毕业设计基于微信小程序的校园外卖订餐系统APP
- 影院在线选座购票API接口
- MYSQL字符串聚合函数
- 阿里云域名解析利用accesskey变动态域名DDNS,简易shell脚本型
- Ogre个人初步学习总结
- java 枚举型 默认值,c# - 选择Enum类型的默认值而不必更改值