Documentation
¶
Index ¶
- Variables
- func IsNegative(err error) bool
- func SetupRedis(configPath string) (err error)
- type CacheAside
- type RedisClient
- func (rc *RedisClient) Del(ctx context.Context, keys ...string) bool
- func (rc *RedisClient) GetObj(ctx context.Context, key string, obj interface{}) (err error)
- func (rc *RedisClient) GetString(ctx context.Context, key string) (result string, err error)
- func (rc *RedisClient) SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) bool
- func (rc *RedisClient) SetObj(ctx context.Context, key string, value interface{}, expiration time.Duration) (err error)
- func (rc *RedisClient) SetString(ctx context.Context, key string, value interface{}, expiration time.Duration) (err error)
- type Store
Constants ¶
This section is empty.
Variables ¶
var ErrNotFound = errors.New("cache: not found, negative cache")
ErrNotFound 穿透函数返回此错误时,CacheAside 写入负缓存(缓存空标记)。 调用方通过 IsNegative 判断命中负缓存。
Functions ¶
func IsNegative ¶ added in v0.2.0
IsNegative 判断错误是否为负缓存哨兵(供 load 内部判断用)。
func SetupRedis ¶
SetupRedis 根据配置名称初始化 Redis configPath 对应 config.Add("redis", ...) 里的 "redis"
Types ¶
type CacheAside ¶ added in v0.2.0
type CacheAside[T any] struct { // contains filtered or unexported fields }
CacheAside 缓存旁路读取器(泛型类型,T 为缓存值类型)。
解决缓存击穿(thundering herd):同一 key 并发 miss 时, 只允许一个请求穿透 DB,其余请求等待并复用结果(singleflight 合并)。
负缓存内置:load 返回 ErrNotFound 时,写入空标记缓存(TTL 内不再穿透 DB), 调用方用返回的 negative 区分"负缓存命中"与"真值缓存命中"。
每个值类型一个实例(NewCacheAside[T]),singleflight group 按实例隔离, 不影响同类型内部按 key 合并。
func NewCacheAside ¶ added in v0.2.0
func NewCacheAside[T any](store Store) *CacheAside[T]
NewCacheAside 构造 CacheAside,显式指定值类型。
func (*CacheAside[T]) Delete ¶ added in v0.2.0
func (c *CacheAside[T]) Delete(ctx context.Context, key string) bool
Delete 删除指定缓存 key(含负缓存)。返回是否删除成功。 用于主动失效(如 MQ 广播触发配置变更后清理缓存)。
func (*CacheAside[T]) DeleteByPrefix ¶ added in v0.2.0
func (c *CacheAside[T]) DeleteByPrefix(ctx context.Context, prefix string) int64
DeleteByPrefix 按 key 前缀删除(含负缓存)。返回删除数量。 用于清理某一类缓存(如某个分销商的所有模型倍率)。
func (*CacheAside[T]) GetOrLoad ¶ added in v0.2.0
func (c *CacheAside[T]) GetOrLoad( ctx context.Context, key string, ttl time.Duration, load func(ctx context.Context) (T, error), ) (T, bool, error)
GetOrLoad 读缓存,miss 则穿透 load 回填(并发合并)。
- 缓存命中(真值):返回 (value, false, nil),无需再查 DB
- 缓存命中(负缓存):返回 (zero, true, nil),调用方按"未配置"处理
- 缓存 miss:singleflight 合并后调 load;load 成功回填真值; load 返回 ErrNotFound 回填负缓存;其他错误透传
回填失败(Redis 写失败)不阻断主流程,仅 Warn 日志。
用法:
aside := cache.NewCacheAside[User]()
val, negative, err := aside.GetOrLoad(ctx, "user:1", time.Hour,
func(ctx context.Context) (User, error) { return db.LoadUser(ctx, 1) })
if negative { /* 未配置/不存在 */ }
type RedisClient ¶
RedisClient 封装结构
func (*RedisClient) GetObj ¶
func (rc *RedisClient) GetObj(ctx context.Context, key string, obj interface{}) (err error)
func (*RedisClient) SetNX ¶ added in v0.1.0
func (rc *RedisClient) SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) bool
SetNX 仅当 key 不存在时设置值,成功返回 true,key 已存在返回 false。
type Store ¶ added in v0.2.0
type Store interface {
GetObj(ctx context.Context, key string, obj interface{}) error
SetObj(ctx context.Context, key string, value interface{}, expiration time.Duration) error
Del(ctx context.Context, keys ...string) bool
DelByPrefix(ctx context.Context, prefix string) int64
}
Store Redis 存储接口(由 *RedisClient 实现,测试可注入桩)。