限流的基本原理及算法实现

本文介绍了系统限流的基本原理和常见算法,包括计数器限流、滑动窗口限流、令牌桶限流和漏桶限流。计数器限流简单但应对突发流量不精确;滑动窗口限流更为精确;令牌桶算法通过发放令牌控制流量,能应对突发流量;漏桶算法以恒定速率处理请求,防止流量突增。四种算法中,漏桶限流对流量控制最佳,但可能增加内存使用。在实际应用中,通常结合使用令牌桶和漏桶限流算法以平衡性能和稳定性。
摘要由CSDN通过智能技术生成

一、限流的基本原理

它的目的是确保系统高效、稳定地运行,确保请求能够快速处理的同时,保障系统不被流量压垮。

限流通常是利用某种算法实现限流器,来达到限制流量的目的。通常,限流器中会有一个定时器,它主要用来定时更新与条件有关的资源。还有,每次请求也需要更新该资源。如果抽象成 Go 中的 interface 话,示例代码如下:

type Limiter interface{
  Take() bool
  Start()
}

其中 Take 方法用于每次请求时调用,判断该请求是否可以继续进行而不触发限流。Start 方法主要用于启动定时器,通常是在工厂方法中创建限流器时调用。示例代码如下:

func NewLimiter(name string, params Params) Limiter {
  var l Limiter
  if name == "counterLimiter" {
    // 创建计数器限流器
    l = newCounterLimiter(params)
  } else if name == "bucketLimiter" {
    // 创建漏桶限流器
    l = newBucketLimiter(params)
  }
  if l != nil {
    l.Start()
  }
  return l
}

限流算法有多种,这两个方法按照不同算法有不同的具体实现。

二、限流算法主要有:计数器限流、滑动窗口限流、令牌桶限流、漏桶限流。

1、计数器限流算法

计数器限流算法也叫固定窗口限流算法。
首先,选定一个时间窗口作为一个周期,假设为 5 秒;

第二步,设定 5 秒内允许通过的流量,如 1000 个请求;

第三步,每次请求,计数器都加 1;

第四步,判断计数器数值是否超过 1000 ,超过了就触发限流策略,如:拒绝或者延迟处理请求等;

最后,如果时间过了 5 秒,则重置计数为 0,开始一个新的周期。

在这里插入图片描述
该限流算法的优点是实现简单,缺点是面对突发流量时不够精确。面对瞬时流量时,会存在资源利用率的剧烈抖动。

2、滑动窗口限流算法

滑动窗口限流算法是对计数器限流算法的优化。它的主要原理是将计数器限流算法中的一个周期拆分成很多等分,比如将 5 秒的周期拆成 5 个 1 秒,每次统计从当前时间开始过去 5 秒内的流量,每隔 1 秒往后滑动 1 秒。
在这里插入图片描述
由于将周期拆分成多个小的单位,相比计数器限流算法,滑动窗口限流算法对流量的统计和控制要更精确,资源利用率抖动更小。但它还是没有彻底解决因瞬时流量导致资源使用率抖动的问题。

那么,有没有办法解决这个问题呢?有,它就是我接下来要介绍的令牌桶限流算法和漏桶限流算法。

3、令牌桶限流算法

令牌桶算法的基本原理是,使用一个定时器以恒定速度往桶里颁发令牌,桶满了则丢弃多余令牌。请看示意图:
在这里插入图片描述
在令牌桶算法中,一般只有拿到令牌的请求才会被处理,没拿到的将会被拒绝。这个过程就像景区的人工售票窗口售票,只有买到票了才能检票进入景区。这其中,令牌就是门票,令牌桶就是售票窗口,负责发令牌的线程就类似于售票员,处理请求的线程就是检票员。

4、漏桶限流算法

漏桶算法的原理跟令牌桶有点相似,只不过漏桶算法采用“生产者-消费者”模型。在“生产者”一端,所有请求进队列,队列满了则丢弃请求。在“消费者”一端,以恒定速度消费队列并处理请求。

在这里插入图片描述
举个例子:乒乓球教练将乒乓球放入到发球机中,乒乓球发球机能以固定速度发出乒乓球,球员可以以固定速度击打乒乓球。例子中的乒乓球相当于软件系统中的请求,教练相当于“生产者”,发球机相当于漏桶,而球员相当于“消费者”。

以上这几种限流算法中,流量控制效果从好到差依次是:漏桶限流 > 令牌桶限流 > 滑动窗口限流 > 计数器限流。

其中,只有漏桶算法真正实现了恒定速度处理请求,能够绝对防止突发流量超过下游系统承载能力。不过,漏桶限流也有个不足,就是需要分配内存资源缓存请求,这会增加内存的使用率。而令牌桶限流算法中的“桶”可以用一个整数表示,资源占用相对较小,这也让它成为最常用的限流算法。

正是因为这些特点,漏桶限流和令牌桶限流经常在一些大流量系统中结合使用。比如秒杀系统中就同时使用了这两种限流算法。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值