cache

package
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Jul 4, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrLockNotHeld   = errors.New("锁未被当前客户端持有")
	ErrLockExpired   = errors.New("锁已过期")
	ErrRedisNotReady = errors.New("Redis 未初始化")
	// ErrLockUnexpectedResult Lua 脚本返回了非预期的结果类型(C1b:裸类型断言防护)。
	ErrLockUnexpectedResult = errors.New("锁脚本返回非预期结果")
)

分布式锁错误

Functions

func AutoInitKeyBuilder

func AutoInitKeyBuilder(opts ...KeyBuilderOption)

AutoInitKeyBuilder 自动从配置初始化键名构建器 配置示例:

app:
  site_name: "site_a"
  env: "prod"

func Decr

func Decr(ctx context.Context, key string) (int64, error)

Decr 自减计数器

func DeleteWithPrefix

func DeleteWithPrefix(ctx context.Context, key string, prefix string) error

DeleteWithPrefix 带前缀的缓存删除

func ExtendLock

func ExtendLock(ctx context.Context, token *LockToken, ttl time.Duration) error

ExtendLock 续期锁 参数: token 锁令牌,ttl 新的过期时间

func ForceUnlock

func ForceUnlock(ctx context.Context, key string) error

ForceUnlock 强制释放锁(危险操作,仅用于管理场景) 注意: 此函数不检查 Token,强制删除锁

M-E 修复:Redis 未初始化时返回 ErrRedisNotReady 而非 nil——原 nil 让调用方误以为 已解锁成功、实则从未操作。管理脚本应据此重试或告警,而非假设成功。

func GetLockTTL

func GetLockTTL(ctx context.Context, key string) (time.Duration, error)

GetLockTTL 获取锁的剩余过期时间。

M-E 修复:Redis 未初始化时返回 (0, ErrRedisNotReady) 而非 (0, nil),调用方可区分 "Redis 不可用"与"锁不存在/已过期"(后者 TTL=-1/-2)。

func GetRaw

func GetRaw(ctx context.Context, key string) (string, error)

GetRaw 获取原始字符串值(不反序列化)

func GetTTL

func GetTTL(ctx context.Context, key string) (time.Duration, error)

GetTTL 获取键的剩余过期时间

func GetWithPrefix

func GetWithPrefix(ctx context.Context, key string, dest any, prefix string) bool

GetWithPrefix 带前缀的缓存获取

func Incr

func Incr(ctx context.Context, key string) (int64, error)

Incr 自增计数器

func IncrBy

func IncrBy(ctx context.Context, key string, value int64) (int64, error)

IncrBy 指定增量自增

func Init

func Init()

Init 初始化全局缓存实例

func InitKeyBuilder

func InitKeyBuilder(prefix string, opts ...KeyBuilderOption)

InitKeyBuilder 初始化全局键名构建器 参数: prefix 站点别名,如果为空则自动从配置读取 示例:

InitKeyBuilder("site_a")                     // 手动指定
InitKeyBuilder("")                            // 自动从配置读取
InitKeyBuilder("", WithSeparator(":"))        // 自动读取 + 自定义分隔符

func IsLocked

func IsLocked(ctx context.Context, key string) (bool, error)

IsLocked 检查锁是否被占用(不获取锁)。

M-E 修复(失败语义统一):Redis 未初始化时返回 (false, ErrRedisNotReady) 而非 (false, nil)—— 后者与"锁确实未被占用"不可区分,调用方可能误以为可获取锁而进入临界区(正确性 bug)。 调用方应 errors.Is(err, ErrRedisNotReady) 区分"Redis 不可用"与"锁未占用"。 L-G 修复:用 .Result() 显式返回 Redis 错误(原 .Val() 吞错致故障被当"未占用")。

契约说明:锁操作有正确性影响(无锁进入临界区 = bug),故 Redis 不可用时显式返错; 与 cache.Get/Set 等数据操作(性能层、best-effort 静默 no-op)区分。

func K

func K(key string) string

K 快捷构建键名(使用全局构建器) 示例: cache.K("user:1") -> 自动添加前缀

func KCounter

func KCounter(key string) string

KCounter 快捷构建计数器键名

func KLock

func KLock(key string) string

KLock 快捷构建锁键名

func KPerm

func KPerm(key string) string

KPerm 快捷构建永久缓存键名

func KSession

func KSession(key string) string

KSession 快捷构建会话键名

func KTemp

func KTemp(key string) string

KTemp 快捷构建临时缓存键名

func Lock

func Lock(ctx context.Context, key string, ttl time.Duration) (bool, error)

Lock 简化的加锁函数(返回 bool) 注意: 使用此函数无法安全释放锁,建议使用 NewLock

func LockWithPrefix

func LockWithPrefix(ctx context.Context, key string, ttl time.Duration, prefix string) (bool, error)

LockWithPrefix 带前缀的分布式锁

func SetDefaultCacheManager added in v1.1.0

func SetDefaultCacheManager(m *CacheManager)

SetDefaultCacheManager 提升指定 CacheManager 为全局默认(atomic 置换,并发安全)。

func SetExpire

func SetExpire(ctx context.Context, key string, ttl time.Duration) (bool, error)

SetExpire 设置键的过期时间

func SetRaw

func SetRaw(ctx context.Context, key string, value string, ttl time.Duration) error

SetRaw 设置原始值(不序列化)

func SetWithPrefix

func SetWithPrefix(ctx context.Context, key string, value any, ttl time.Duration, prefix string) error

SetWithPrefix 带前缀的缓存设置

func Unlock

func Unlock(ctx context.Context, token *LockToken) error

Unlock 安全释放锁

func UnlockByKey

func UnlockByKey(ctx context.Context, key string) error

UnlockByKey 按键名释放锁(不安全,仅用于旧代码兼容) 注意: 此函数不检查 Token,任何客户端都能释放锁

func UnlockWithPrefix

func UnlockWithPrefix(ctx context.Context, key string, prefix string) error

UnlockWithPrefix 带前缀的锁释放 注意: 此函数不检查 Token,仅用于向后兼容,建议使用 NewLock/Unlock 组合

func WithLock

func WithLock(ctx context.Context, key string, ttl time.Duration, fn func() error) error

WithLock 使用分布式锁执行函数(自动管理锁)。 参数: key 锁名称,ttl 锁定时长,fn 业务函数 注意: 如果任务执行时间超过 ttl,需要设置更长的 ttl 或使用 WithLockAutoExtend。

解锁用独立 Background ctx(C1a 一致性修复):fn 返回或 panic 后,原 ctx 可能已被 调用方取消,用其解锁会失败导致锁泄漏到 TTL。fn panic 时 defer 也保证解锁执行。

func WithLockAutoExtend

func WithLockAutoExtend(ctx context.Context, key string, initialTTL time.Duration, extendInterval time.Duration, fn func() error) error

WithLockAutoExtend 使用分布式锁执行函数(自动续期)。 参数: key 锁名称,initialTTL 初始锁定时长,extendInterval 续期间隔,fn 业务函数

并发安全说明(C1a 修复):续期 goroutine 与父用"父关停 + 子 ack"双 channel 协调—— 父用 close(stop) 通知子退出(close 由唯一所有者执行,安全),子用 close(finished) ack。 避免旧实现 done 无缓冲 + 子 defer close(done) + 父 done<-struct{}{} 的 send-on-closed panic (ctx 取消或 ExtendLock 失败时 done 已 closed,父再 send 即 panic,Unlock 不执行、锁泄漏到 TTL)。 Unlock 用 context.Background() 派生超时,避免原 ctx 已取消致 Unlock 失败再泄漏。

Types

type CacheManager added in v1.1.0

type CacheManager struct {
	// contains filtered or unexported fields
}

CacheManager 缓存管理器(#10)。照 database.Manager 模式: 实例化 + DefaultCache 全局默认 + 包级 facade 代理,支持测试注入 mock 实现。

func GetDefaultCache added in v1.2.0

func GetDefaultCache() *CacheManager

GetDefaultCache 返回全局默认缓存管理器(并发安全,CK3 修复)。

func NewCacheManager added in v1.1.0

func NewCacheManager() *CacheManager

NewCacheManager 创建缓存管理器实例。

func (*CacheManager) Get added in v1.1.0

func (m *CacheManager) Get() CacheService

Get 返回缓存服务(未初始化时延迟初始化)。

func (*CacheManager) Init added in v1.1.0

func (m *CacheManager) Init()

Init 初始化缓存服务(基于 DefaultRedis 的客户端)。

func (*CacheManager) Set added in v1.1.0

func (m *CacheManager) Set(svc CacheService)

Set 设置缓存服务实现(用于注入 mock 或自定义实现)。

type CacheService

type CacheService interface {
	// Get 获取缓存值,如果存在则反序列化到 dest 并返回 true
	Get(ctx context.Context, key string, dest any) bool
	// Set 设置缓存值
	Set(ctx context.Context, key string, value any, ttl time.Duration) error
	// Delete 删除缓存
	Delete(ctx context.Context, key string) error
	// DeleteByPattern 按模式删除缓存
	DeleteByPattern(ctx context.Context, pattern string) error
	// Exists 检查缓存是否存在
	Exists(ctx context.Context, key string) bool
}

CacheService 缓存服务接口

func GetCache

func GetCache() CacheService

GetCache 获取全局缓存实例

func NewRedisCache

func NewRedisCache() CacheService

NewRedisCache 创建 Redis 缓存实例

type KeyBuilder

type KeyBuilder struct {
	// contains filtered or unexported fields
}

KeyBuilder 缓存键名构建器(CK2 修复:mu 保护并发访问)。 使用场景: 多个小项目共用一台 Redis 服务器,每个项目设置不同前缀

func GetKeyBuilder

func GetKeyBuilder() *KeyBuilder

GetKeyBuilder 获取全局键名构建器,未初始化时用 sync.Once 自动初始化一次(M13)。

func NewKeyBuilder

func NewKeyBuilder(opts ...KeyBuilderOption) *KeyBuilder

NewKeyBuilder 创建键名构建器

func (*KeyBuilder) Build

func (kb *KeyBuilder) Build(key string) string

Build 构建完整键名(CK2 修复:mu 读保护)。 格式: {cacheType}{separator}{prefix}{separator}{key} 示例: kb.Build("user:1") -> "cache_site_a_user:1"

func (*KeyBuilder) BuildCounter

func (kb *KeyBuilder) BuildCounter(key string) string

BuildCounter 构建计数器键名(CK2 修复:mu 读保护)。 格式: "counter{separator}{prefix}{separator}{key}"

func (*KeyBuilder) BuildLock

func (kb *KeyBuilder) BuildLock(key string) string

BuildLock 构建分布式锁键名(CK2 修复:mu 读保护)。 格式: "lock{separator}{prefix}{separator}{key}"

func (*KeyBuilder) BuildPattern

func (kb *KeyBuilder) BuildPattern(pattern string) string

BuildPattern 构建匹配模式(用于 SCAN/Keys)(CK2 修复:mu 读保护)。 示例: kb.BuildPattern("user:*") -> "cache_site_a_user:*"

func (*KeyBuilder) BuildPerm

func (kb *KeyBuilder) BuildPerm(key string) string

BuildPerm 构建永久缓存键名(CK2 修复:mu 读保护)。 格式: "perm{separator}{prefix}{separator}{key}"

func (*KeyBuilder) BuildSession

func (kb *KeyBuilder) BuildSession(key string) string

BuildSession 构建会话键名(CK2 修复:mu 读保护)。 格式: "session{separator}{prefix}{separator}{key}"

func (*KeyBuilder) BuildTemp

func (kb *KeyBuilder) BuildTemp(key string) string

BuildTemp 构建临时缓存键名(CK2 修复:mu 读保护)。 格式: "temp{separator}{prefix}{separator}{key}"

func (*KeyBuilder) GetPrefix

func (kb *KeyBuilder) GetPrefix() string

GetPrefix 获取当前前缀(CK2 修复:mu 读保护)。

func (*KeyBuilder) SetPrefix

func (kb *KeyBuilder) SetPrefix(prefix string) *KeyBuilder

SetPrefix 动态设置前缀(CK2 修复:mu 写保护,并发安全)。

type KeyBuilderOption

type KeyBuilderOption func(*KeyBuilder)

KeyBuilderOption 配置选项

func WithCacheType

func WithCacheType(cacheType string) KeyBuilderOption

WithCacheType 设置缓存类型标识 示例: WithCacheType("session") -> "session_site_a_user:1"

func WithPrefix

func WithPrefix(prefix string) KeyBuilderOption

WithPrefix 设置前缀(项目/站点别名) 示例: WithPrefix("site_a") -> 所有 key 自动添加 "site_a" 前缀

func WithSeparator

func WithSeparator(separator string) KeyBuilderOption

WithSeparator 设置分隔符 示例: WithSeparator(":") -> "site_a:user:1"

type LockToken

type LockToken struct {
	Key   string // 锁的键名
	Token string // 锁的唯一标识(UUID)
}

LockToken 锁令牌(用于安全释放锁)。

安全说明(C1d 设计局限):Token 是随机 UUID(非单调递增的 fencing token)。 本实现基于 Redis SET PX + Lua CAS,保证"持有者才能解锁/续期",但**无法防 TTL 到期后的 双 worker 并发**:若 worker A 因 GC/网络停滞超过 TTL,锁过期后 worker B 获得锁, A 恢复后仍可能写过期数据。完整的 fencing token 防护需:① 用 Redis INCR 生成单调 token, ② 下游存储层(DB/外部服务)记录已见最大 token 并拒绝旧 token 写入。 框架无法单方面保证②,需下游配合,故本类型仅提供 UUID token。对 TTL 到期敏感的场景, 请确保 ttl >> 业务最长执行时间,或下游实现 fencing token 校验。

func NewLock

func NewLock(ctx context.Context, key string, ttl time.Duration) (*LockToken, error)

NewLock 创建分布式锁 参数: key 锁名称,ttl 锁定时长 返回: LockToken 用于后续解锁或续期

func TryLock

func TryLock(ctx context.Context, key string, ttl time.Duration, retryInterval time.Duration, maxRetry int) (*LockToken, error)

TryLock 尝试获取锁,失败时等待重试。重试等待响应 ctx 取消(C1c 修复)。

Jump to

Keyboard shortcuts

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