返回

基于滑动时间窗口的「预热桶」限流算法揭秘

前端

现代分布式系统中,QPS (每秒查询数) 是一个重要的性能指标。它衡量了系统每秒能够处理的请求数量。当请求量超过系统所能承受的阈值时,系统就会出现拥塞,导致性能下降,甚至崩溃。

限流是一种保护系统免受过载的常用技术。它通过限制每秒允许进入系统的请求数量,来防止系统被过多的请求压垮。

「预热桶」限流算法是一种基于滑动时间窗口的限流算法。它将时间划分为一个个固定大小的窗口,并在每个窗口内允许一定数量的请求通过。当窗口内的请求数量达到阈值时,超过阈值的请求就会被拒绝。

「预热桶」限流算法的主要优点是,它可以动态调整限流阈值,以适应系统流量的变化。当系统流量较低时,限流阈值可以调高,以允许更多的请求通过。当系统流量较高时,限流阈值可以调低,以防止系统过载。

算法原理

「预热桶」限流算法的工作原理如下:

  1. 将时间划分为一个个固定大小的窗口,窗口的大小通常为 1 秒或 1 分钟。
  2. 在每个窗口内,允许一定数量的请求通过。这个数量称为「预热桶」容量。
  3. 当窗口内的请求数量达到「预热桶」容量时,超过容量的请求就会被拒绝。
  4. 每个窗口都有一个滑动时间窗口。当窗口到期时,窗口内的所有请求都会被清除,并且「预热桶」容量会重置。

Go语言实现

package main

import (
    "fmt"
    "sync"
    "time"
)

type PrewarmBucket struct {
    // 预热桶容量
    capacity int
    // 滑动时间窗口大小
    windowSize time.Duration
    // 当前窗口内已处理的请求数
    currentCount int
    // 上一个窗口内已处理的请求数
    previousCount int
    // 滑动时间窗口的开始时间
    startTime time.Time
    // 互斥锁,用于保护并发访问
    mu sync.Mutex
}

func NewPrewarmBucket(capacity int, windowSize time.Duration) *PrewarmBucket {
    return &PrewarmBucket{
        capacity:     capacity,
        windowSize:   windowSize,
        startTime:    time.Now(),
        currentCount: 0,
        previousCount: 0,
    }
}

// 允许一个请求通过
func (b *PrewarmBucket) Allow() bool {
    b.mu.Lock()
    defer b.mu.Unlock()

    // 检查当前窗口是否已满
    if b.currentCount >= b.capacity {
        return false
    }

    // 更新当前窗口内已处理的请求数
    b.currentCount++

    // 检查滑动时间窗口是否已到期
    if time.Since(b.startTime) >= b.windowSize {
        // 重置滑动时间窗口
        b.startTime = time.Now()
        // 将上一个窗口内已处理的请求数设置为当前窗口内已处理的请求数
        b.previousCount = b.currentCount
        // 重置当前窗口内已处理的请求数
        b.currentCount = 0
    }

    return true
}

func main() {
    // 创建一个预热桶限流器,容量为 100,滑动时间窗口大小为 1 秒
    limiter := NewPrewarmBucket(100, time.Second)

    // 模拟 1000 个请求
    for i := 0; i < 1000; i++ {
        // 尝试允许一个请求通过
        if limiter.Allow() {
            // 请求通过,处理请求
            fmt.Println("请求", i, "通过")
        } else {
            // 请求被拒绝,返回错误
            fmt.Println("请求", i, "被拒绝")
        }
    }
}

结语

「预热桶」限流算法是一种简单高效的限流算法。它易于实现,并且可以动态调整限流阈值,以适应系统流量的变化。在分布式系统中,它是一种常用的限流算法。