Documentation
¶
Overview ¶
Package counter 提供按 key 的滑动窗口计数与时间窗配额,纯内存实现。
与 pkg/ratelimit 的区别(互补):
- ratelimit 控制"速率"(令牌桶:每秒 N 个、匀速放行),关心节奏;
- counter 控制"窗口内累计次数"(滑动窗口:某时间段内总共 N 次,不管节奏), 关心总量。典型:每日抽卡 100 次、1 分钟弹幕 ≤ 60 条、活动限领 3 次、 点赞/关注防刷。这类"配额"用令牌桶表达并不自然,用时间窗计数才贴切。
实现:每个 key 一个环形桶(把 window 切成 buckets 份),Incr 落到当前时间对应 的桶;Count 求和所有未过期桶。滑动而非固定窗口——避免固定窗口临界点的双倍突发。 bucket 数越多,窗口滑动越平滑,内存与求和成本越高(默认 10)。
并发安全(分片锁减少争用)。零值不可用,用 New 构造;Stop 后 gc goroutine 退出。
生产多实例:默认内存实现的计数不跨实例(每台各算各的,配额可被绕过)。用 WithStore 接入 kvstore.Store(如 Redis)后,计数跨实例一致。注意:store 模式用 固定窗口(每个 window 一个带 TTL 的计数 key),而非内存模式的滑动窗口——固定窗口 在窗口边界可能出现最多 2 倍瞬时突发,换取"用一次原子 INCR 就能跨实例计数"的简单可靠。
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Counter ¶
type Counter struct {
// contains filtered or unexported fields
}
Counter 滑动窗口计数器。按 key 维护独立的时间窗累计。 零值不可用,用 New 构造。并发安全。
func (*Counter) Allow ¶
Allow 判断 key 再增加 n 后是否仍不超过 limit:不超则增加并返回 true, 超过则不增加并返回 false。用于"窗口内配额"控制(如每日抽卡上限)。
store 模式下用"先增后判、超限回退"实现原子配额:先 Incr,若超限则 Incr(-n) 退回。 高并发下计数瞬时可能越过 limit 但会立即回退,最终不会真正记入超限的量。
type Option ¶
type Option func(*config)
Option 配置 Counter。
func WithGCInterval ¶
WithGCInterval 设置空闲 key 清扫间隔(默认取 window,至少 1s)。
func WithOnStoreError ¶
WithOnStoreError 设置 store 操作出错时的回调(网络故障等)。默认静默; 出错时读操作返回 0、Allow 放行(fail-open),由此回调上报供监控。