以下是使用golang和redis实现滑动窗口限流的示例代码:
package main
import (
"fmt"
"time"
"github.com/go-redis/redis"
)
func main() {
client := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
})
const limit = 10 // 每秒限制请求数
const window = 1000 // 时间窗口,单位为毫秒
for {
start := time.Now().UnixNano() / int64(time.Millisecond) // 获取当前时间戳
count, err := client.Incr("req_count").Result()
if err != nil {
panic(err)
}
if count == 1 { // 如果是第一次请求,则设置过期时间
client.Expire("req_count", time.Duration(window)*time.Millisecond)
}
if count > limit { // 如果请求数超过限制,则返回错误信息
fmt.Println("Rate limited")
break
}
elapsed := (time.Now().UnixNano() / int64(time.Millisecond)) - start
time.Sleep(time.Duration(window)*time.Millisecond - time.Duration(elapsed)*time.Millisecond) // 等待剩余时间,进入下一个时间窗口
}
}
该示例使用Redis的Incr命令来自增计数器,并在每个时间窗口内检查计数器是否超过限制。如果超过了限制,则返回错误信息。同时,在第一次请求时,还会设置计数器的过期时间为一个时间窗口。
该示例仅作为演示用途,实际应用中还需要考虑并发访问的情况以及在Redis集群下的实现。