cache

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Aug 3, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("cache: not found, negative cache")

ErrNotFound 穿透函数返回此错误时,CacheAside 写入负缓存(缓存空标记)。 调用方通过 IsNegative 判断命中负缓存。

Functions

func IsNegative added in v0.2.0

func IsNegative(err error) bool

IsNegative 判断错误是否为负缓存哨兵(供 load 内部判断用)。

func SetupRedis

func SetupRedis(configPath string) (err error)

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

type RedisClient struct {
	Client *redis.Client
	// contains filtered or unexported fields
}

RedisClient 封装结构

func Instance

func Instance() *RedisClient

Instance 对外暴露的单例获取函数

func (*RedisClient) Del

func (rc *RedisClient) Del(ctx context.Context, keys ...string) bool

func (*RedisClient) GetObj

func (rc *RedisClient) GetObj(ctx context.Context, key string, obj interface{}) (err error)

func (*RedisClient) GetString

func (rc *RedisClient) GetString(ctx context.Context, key string) (result string, 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。

func (*RedisClient) SetObj

func (rc *RedisClient) SetObj(ctx context.Context, key string, value interface{}, expiration time.Duration) (err error)

func (*RedisClient) SetString

func (rc *RedisClient) SetString(ctx context.Context, key string, value interface{}, expiration time.Duration) (err error)

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 实现,测试可注入桩)。

Jump to

Keyboard shortcuts

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