counter

package
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 15, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

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 New

func New(window time.Duration, opts ...Option) *Counter

New 创建滑动窗口计数器。window 为统计窗口长度(如 time.Minute、24*time.Hour)。

func (*Counter) Add

func (c *Counter) Add(key string, n int64) int64

Add 是 Incr 的别名,语义更通用。

func (*Counter) Allow

func (c *Counter) Allow(key string, n, limit int64) bool

Allow 判断 key 再增加 n 后是否仍不超过 limit:不超则增加并返回 true, 超过则不增加并返回 false。用于"窗口内配额"控制(如每日抽卡上限)。

store 模式下用"先增后判、超限回退"实现原子配额:先 Incr,若超限则 Incr(-n) 退回。 高并发下计数瞬时可能越过 limit 但会立即回退,最终不会真正记入超限的量。

func (*Counter) Count

func (c *Counter) Count(key string) int64

Count 返回 key 在当前窗口内的累计值(不修改)。

func (*Counter) Incr

func (c *Counter) Incr(key string, n int64) int64

Incr 给 key 增加 n(n 可为任意正整数,如礼物数量)。返回增加后的当前窗口累计值。

func (*Counter) Reset

func (c *Counter) Reset(key string)

Reset 清零 key 的计数(删除其状态)。store 模式删除当前窗口的计数键。

func (*Counter) Stop

func (c *Counter) Stop()

Stop 停止 gc goroutine。幂等。

type Option

type Option func(*config)

Option 配置 Counter。

func WithBuckets

func WithBuckets(n int) Option

WithBuckets 设置窗口切分的桶数(默认 10)。越大滑动越平滑,成本越高。

func WithGCInterval

func WithGCInterval(d time.Duration) Option

WithGCInterval 设置空闲 key 清扫间隔(默认取 window,至少 1s)。

func WithOnStoreError

func WithOnStoreError(fn func(op, key string, err error)) Option

WithOnStoreError 设置 store 操作出错时的回调(网络故障等)。默认静默; 出错时读操作返回 0、Allow 放行(fail-open),由此回调上报供监控。

func WithStore

func WithStore(s kvstore.Store) Option

WithStore 让计数走外部共享存储(如 Redis 实现的 kvstore.Store),使计数跨实例一致。 配置后 Incr/Count/Allow 路由到 store(固定窗口),不再使用内存分片与 gc。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL