首页 > 编程知识 正文

redis实现分布式限流,流量控制和拥塞控制

时间:2023-05-05 23:31:29 阅读:116243 作者:1369

流量限制控制:在高同时系统中如何操作流量? 限流是什么是需要知道的限流算法固定窗口和滑动窗口算法漏桶算法和令牌桶算法总结

如果系统的高峰流量超过预期高峰,核心服务也会受到很大影响,但是否可能会降低整个核心服务? 那么,此时如何保证服务的稳定性呢? 我觉得可以使用限流的方案。 而且,说到限流,我相信我们多少在以下地方错过了。

发现虽然开启了限流算法选择不当、限流效果不佳的限流,但整体性能存在损失; 只实现了单体限流,没有实现整个系统的限流; 说白了,这些问题的产生还是因为不熟悉限流的算法和实用。

最初,流限制是指通过限制到达系统的并发请求的数量,来确保系统能够成功响应某些用户请求,而对于超出限制的通信,则通过拒绝服务来确保整个系统的可用性。 流限制策略通常部署在服务(如API网关)的条目层上,以整形整个系统的流量。 在微服务体系结构中,还可以在RPC客户端上实施流限制策略,以防止单个服务被过大的流量压坏。

其实,无论是在实际的工作生活中,还是之前学习的知识中,都可能被应用于限流战略中。 让我举几个例子。

例如,十一黄金周想去一个景区玩,到了发现景区有临时通知,每天只卖10万张票,当天没有抢票的游客只能第二天一大早来抢票。 这是一种常见的限流策略,通过整体控制一定时间(这里是一天)的流量,可以避免游客过多,景区环境受到影响的情况,确保游客的安全。 而且,如果挤过地铁的话,会更加有共鸣。 北京早早繁荣的舞蹈地铁受到限制。 思路很直接,就是控制进入地铁的人数,避免地铁破裂,尽量保障人们的安全。

例如,TCP协议具有滑动窗口的概念,其能够控制网络传输业务。 可以想象,如果没有流控制,即使流接收方的处理速度变慢,如果发送方继续以以前的速率发送数据,流必然会拥塞。 另一方面,TCP的滑动窗口实际上可以视为接收方提供的缓冲器的大小。

收件人回复发件人的ACK消息将携带此窗口的大小。 据此,发送侧能够决定在该滑动窗口的大小中发送数据的速率。 如果接收方处理了几个缓冲器中的数据,则此滑动窗口会变大,发送方发送数据的速度会加快,相反,如果接收方接收到几个数据还来不及处理,则此滑动窗口会变小,发送方发送数据

无论是一体化体系结构还是微服务化体系结构,都可以通过多个维来控制到达系统的通信量,包括

限制系统每分钟可以处理的请求数量; 对于一个接口,可以设置每分钟的请求通信量限制。 您可以限制一个IP、用户ID或设备ID在一段时间内发送的请求数。 在为多个第三方APP应用程序提供服务的开放平台上,每个第三方APP应用程序都由平台端唯一的appkey标识,因此还可以限制单个appkey访问接口的速度实现上述限速的方法基于几种限制流算法,那么常见的限制流算法是什么? 实现限流时有什么方法?

我们知道,固定限流算法窗口和滑动窗口的算法在于限制限流的目的是限制在一段时间内发送到系统的总体需求量。 例如,如果限制系统在一分钟内只接受一万次请求,最暴力的方法之一是记录在这一分钟内有多少请求访问系统,如果超过一万次限制,则下游策略会返回请求失败的错误如果这一分钟的请求数未达到限制,则在下一分钟到来时重置请求数计数,然后统计这一分钟的请求数是否超过限制。

该算法称为固定窗口算法,在实现它时,首先启动计时器定期重置计数。

流限制逻辑非常简单,只需比较计数值是否大于阈值。

该算法非常容易实现,但有很大的缺点。 无法限制短时间内的集中流量。 如果要求限制为每秒只能处理10次请求,则如果前一秒发生10次请求,则这10次请求全部集中在最后10毫秒;如果下一秒的前10毫秒也发生10次请求,则这20毫秒但是,这20次请求分布在两个时间窗口中,因此不存在流限制,流限制策略无效。

为了解决这个缺点,有一种基于滑动窗口的算法。 该算法的原理是将一个时间窗口分割成多个小窗口,并且每个小窗口具有各自的请求数目。 例如,在下图中,将1秒的时间窗分为5个。 每个为200ms。 在中,如果1s和1.2s之间出现新请求,则必须统计之前1秒钟的请求量,即1.2s到1.2s区间的总请求量,如果请求量超过流限制阈值,则必须运行流限制策略。

滑动窗口算法解决了临界时间点无法进行突发流量控制的问题,但由于存储了每个小时间窗口的计数,因此增加了空间复杂度。

滑动窗口算法可以解决窗口边界上的大流量问题,但与固定窗口算法一样,它不能限制短时间内的集中流量。 也就是说,无法更顺利地控制流量。因此,在实际的项目 中,很少使用基于时间窗口的限流算法,而是使用其他限流的算法:一种算法叫

做漏桶算 法,一种叫做令牌筒算法。

漏桶算法与令牌筒算法

漏桶算法的原理很简单,它就像在流量产生端和接收端之间增加一个漏桶,流量会进入和暂存到漏桶里面,而漏桶的出口处会按照一个固定的速率将流量漏出到接收端(也就是服务接口)。

如果流入的流量在某一段时间内大增,超过了漏桶的承受极限,那么多余的流量就会触发限流策略,被拒绝服务。

经过了漏桶算法之后,随机产生的流量就会被整形成为比较平滑的流量到达服务端,从而避免了突发的大流量对于服务接口的影响。这很像九阳真经的口诀:他强由他强,清风拂山岗,他横由他横,明月照大江 。 也就是说,无论流入的流量有多么强横,多 么不规则,经过漏桶处理之后,流出的流量都会变得比较平滑

而在实现时,我们一般会使用消息队列作为漏桶的实现,流量首先被放入到消息队列中排队,由固定的几个队列处理程序来消费流量,如果消息队列中的流量溢出,那么后续的流量就会被拒绝。这个算法的思想是不是与消息队列削峰填谷的作用相似呢?


另一种令牌桶算法的基本算法是这样的:

如果我们需要在一秒内限制访问次数为 N 次,那么就每隔 1/N 的时间,往桶内放入一个 令牌;在处理请求之前先要从桶中获得一个令牌,如果桶中已经没有了令牌,那么就需要等待 新的令牌或者直接拒绝服务;桶中的令牌总数也要有一个限制,如果超过了限制就不能向桶中再增加新的令牌了。这 样可以限制令牌的总数,一定程度上可以避免瞬时流量繁荣的舞蹈的问题。

如果要从这两种算法中做选择,我更倾向于使用令牌桶算法,原因是漏桶算法在面对突发流量的时候,采用的解决方式是缓存在漏桶中, 这样流量的响应时间就会增长,这就与互联 网业务低延迟的要求不符;而令牌桶算法可以在令牌中暂存一定量的令牌,能够应对一定的 突发流量,所以一般我会使用令牌桶算法来实现限流方案,而 Guava 中的限流方案就是使 用令牌桶算法来实现的。

可以看到,使用令牌桶算法就需要存储令牌的数量,如果是单机上实现限流的话,可以在进程中使用一个变量来存储;但是如果在分布式环境下,不同的机器之间无法共享进程中的 变量,我们就一般会使用 Redis 来存储这个令牌的数量。这样的话,每次请求的时候都需 要请求一次 Redis 来获取一个令牌,会增加几毫秒的延迟,性能上会有一些损耗。因此, 一个折中的思路是: 我们可以在每次取令牌的时候,不再只获取一个令牌,而是获取一批 令牌,这样可以尽量减少请求 Redis 的次数。

总结

我们了解了限流的定义和作用,以及常见的几种限流算法,我们需要了解的重点是:

限流是一种常见的服务保护策略,你可以在整体服务、单个服务、单个接口、单个 IP 或 者单个用户等多个维度进行流量的控制;基于时间窗口维度的算法有固定窗口算法和滑动窗口算法,两者虽然能一定程度上实现限流的目的,但是都无法让流量变得更平滑;令牌桶算法和漏桶算法则能够塑形流量,让流量更加平滑,但是令牌桶算法能够应对一定的突发流量,所以在实际项目中应用更多。

限流策略是微服务治理中的标配策略,只是你很难在实际中确认限流的阈值是多少,设置的小了容易误伤正常的请求,设置的大了则达不到限流的目的。所以,一般在实际项目中,我们会把阈值放置在配置中心中方便动态调整;同时,我们可以通过定期地压力测试得到整体系统以及每个微服务的实际承载能力,然后再依据这个压测出来的值设置合适的阈值。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。