并发必备技能 - 流量控制

      在双十一、618 等大促的场景下,我们系统的实际流量峰值可能会超过预估的峰值,而流量控制则可以在这种情况下为我们的应用保驾护航,简而言之流控可以保障系统稳定运行避免资源耗尽提高系统吞吐量提高用户体验。

  • 系统稳定性:高并发时,系统会面临大量的请求同时到达,如果不进行流量控制,系统可能会超出其处理能力范围,导致系统崩溃或变得非常缓慢。通过控制流量,可以限制同时处理的请求数量,从而保护系统的稳定性和可用性。
  • 避免资源耗尽:高并发情况下,系统的资源包括CPU、内存、数据库连接等容易被耗尽。如果没有流量控制,每个请求都可能占用大量的资源,导致其他请求无法得到足够的资源。通过流量控制,可以限制每个请求占用的资源数量,确保资源被合理分配,避免资源耗尽的情况发生
  • 提高系统吞吐量:在高并发场景下,流量控制可以帮助系统平稳处理请求,避免过多的请求同时涌入,导致系统瓶颈。通过适当地控制流量,可以使系统在可承受范围内运行,提高系统的吞吐量和性能
  • 提高用户体验流量控制可以防止系统过载,提高系统的响应速度和稳定性,从而为用户提供更好的体验。通过合理的流量控制策略,可以避免用户长时间等待或请求失败的情况,提高用户满意度

      流控(限流)即通过限制到达系统的并发请求数量,保证系统能够正常响应部分用户请求,而对于超过限制的流量,则只能通过拒绝服务的方式保证整体系统的可用性。参与过秒杀或者抢票的同学肯定深有体会,那么实现流控的算法主要有哪些呢 ?

1、 固定窗口算法(Fixed Window Algorithm)

并发必备技能 - 流量控制_第1张图片

       将时间分成固定的窗口,例如每秒、每分钟或每小时等。在每个窗口期间,系统记录请求的数量,并与预设的阈值进行比较。如果请求数量超过阈值,系统可能会拒绝或延迟处理请求。然后,在下一个窗口开始时,计数器重置为零,重新开始计数。该算法实现非常简单,但是有一个很大的缺陷 ,无法限制短时间之内的集中流量。如:1分钟内限制100次请求,有可能这100次会都集中在第一秒中。

重点:

  • 将时间划分为固定的窗口,例如每秒、每分钟或每小时等。
  • 在每个窗口期,系统记录请求的数量,并与预设的阈值进行比较。
  • 如果请求数量超过阈值,系统可能会拒绝或延迟处理请求。
  • 然后,在下一个窗口开始时,计数器重置为零,重新开始计数。

2、滑动窗口算法(Sliding Window Algorithm)

并发必备技能 - 流量控制_第2张图片

       基于时间窗口的流量控制算法,它将单位时间划分为多个小的时间片段,在每个时间片段内限制请求的数量。随着时间的推移,窗口不断向前滑动,旧的时间片段被丢弃,新的时间片段加入到流量计算中,举个例子:把1秒的时间窗口分为4分,每个窗口单独计数,每次请求到来时,统计的都是当前时间窗口 ~ 前3个窗口的总和,是否超出限制次数。

重点:

  • 将时间划分为多个窗口,但窗口之间有重叠。
  • 窗口随着时间的推移滑动,旧的窗口被丢弃,新的窗口加入到流量计算中。
  • 在每个窗口期间,系统记录请求的数量,并与预设的阈值进行比较。
  • 如果请求数量超过阈值,系统可能会拒绝或延迟处理请求。
  • 与固定窗口算法不同的是,滑动窗口算法在计数器的重置上没有固定的时间点,而是根据窗口的滑动进行计数。

       滑动窗口的算法解决了临界时间点上突发流量无法控制的问题,但是却因为要存储每个小的时间窗口内的计数,所以空间复杂度有所增加。同时它无法实现限制短时间之内的集中流量,也就是说无法控制流量让它们更加平滑。

3、令牌桶算法(Token Bucket Algorithm)

并发必备技能 - 流量控制_第3张图片

       一种基于令牌的流量控制算法。系统维护一个令牌桶,桶中包含一定数量的令牌,每个令牌代表一个请求的许可。当请求到达时,如果桶中有足够的令牌,则请求被允许通过,并从桶中取走一个令牌;如果桶中没有令牌,则请求被暂时阻塞或丢弃。可以限制请求的速率,并允许突发请求在一定程度上通过,同时保持整体的速率控制。Guava 中的限流方案就是使用令牌桶算法来实现的

优点:

  • 灵活控制请求速率:令牌桶算法通过令牌的生成速率来控制请求的速率,可以灵活地调整速率限制。
  • 对突发流量有较好的处理能力:令牌桶算法可以在一定程度上处理突发请求,因为它允许一定数量的请求在短时间内通过。

缺点:

  • 复杂实现:相对于漏桶算法,令牌桶算法的实现稍微复杂一些,需要维护令牌桶和令牌的生成逻辑。
  • 令牌桶容量限制:令牌桶算法需要维护一个令牌桶,其容量可能占用一定的内存资源。

4、漏桶算法

并发必备技能 - 流量控制_第4张图片

       请求像水滴一样进入漏桶。漏桶以固定的速率漏水,当请求到达时,如果桶还有空间,请求被放入桶中并被处理;如果桶已满,则请求被拒绝或延迟处理。经过漏桶处理之后,流出的流量都会变得比较平滑,就像在流量产生端和接收端之间增加一个漏桶,流量会进入和暂 存到漏桶里面,而漏桶的出口处会按照一个固定的速率将流量漏出到接收端。

        实际使用中,我们一般会使用消息队列作为漏桶的实现,流量首先被放入到消息队列中排 队,由固定的几个队列处理程序来消费流量,如果消息队列中的流量溢出,那么后续的流量就会被拒绝。

优点:

  • 流量平滑:漏桶算法以固定的速率处理请求,可以平滑请求的流量,避免突发请求对系统造成冲击。
  • 简单实现:漏桶算法相对简单,易于理解和实现

缺点:

  • 对突发流量的处理有限:漏桶算法无法处理突发请求,当请求速率超过漏桶的处理能力时,会丢弃部分请求,可能导致用户体验下降。

总结

        限流是一种常见的服务保护策略,可以在整体服务、单个服务、单个接口、单个 IP 或 者单个用户等多个维度进行流量的控制,在实际使用中我们选择限流方式时,需要先了解系统需要的流量模式,评估不同算法的特性、复杂度和性能影响,进行实验和测试,根据结果选择最适合的算法。

你可能感兴趣的:(#,并发编程,限流,并发)