網頁

2024/4/30

Golang Redis 固定窗口限流器 fixed window rate limiter

Go利用Redis實作簡單的「固定窗口限流器(Fixed window rate limiter)」。


main.go

package main

import (
    "context"
    "fmt"
    "time"

    "github.com/go-redis/redis/v9"
)

func main() {
    ctx := context.Background()
    rc := NewRedisClient()

    userId := "user123" // request's user id
    reqCount := 10      // intense request count of the user

    for i := 0; i < reqCount; i++ { // send intense requests
        currentMinute := time.Now().Minute() // request time minute
        if isAllowed(ctx, rc, userId, currentMinute) {
            fmt.Println("pass")
        } else {
            fmt.Println("reject")
        }
    }

}

func isAllowed(ctx context.Context, rc *redis.Client, userId string, currentMiniute int) bool {
    key := fmt.Sprintf("%s:%d", userId, currentMiniute) // e.g. key=user123:45
    n, _ := rc.Get(ctx, key).Int()
    limit := 5 // limit request count within the time window
    if n >= limit {
        return false
    }

    pipe := rc.TxPipeline() // redis MULTI/EXEC
    pipe.Incr(ctx, key)
    pipe.Expire(ctx, key, time.Minute) // 1minute fixed time window
    _, err := pipe.Exec(ctx)
    return err == nil
}

func NewRedisClient() *redis.Client {
    return redis.NewClient(&redis.Options{
        Addr:     "localhost:6379",
        Password: "12345",
        DB:       0, // use default DB
    })
}

github



測試

執行印出以下。

pass
pass
pass
pass
pass
reject
reject
reject
reject
reject


沒有留言:

張貼留言