You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
2.3 KiB
82 lines
2.3 KiB
package cache
|
|
|
|
/*
|
|
通用 Redis 缓存层:基于 Redis Hash 的"全量数据集"缓存。
|
|
|
|
一个数据集 = 一个 Redis Hash(key = redissys.RKey(name),field = 主键字符串,value = JSON)。
|
|
适合"管理后台维护、低频变更、高频读取"的引用数据(如 product),配合
|
|
全量预热 + 定时刷新 + 事件驱动刷新使用,使读请求恒命中 Redis。
|
|
|
|
复用 lego/sys/redis 已初始化的客户端(redissys.Conn)与统一 key 前缀(redissys.RKey)。
|
|
*/
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"time"
|
|
|
|
redissys "yunyan/lego/sys/redis"
|
|
|
|
"github.com/redis/go-redis/v9"
|
|
)
|
|
|
|
// ReplaceAll 用全量数据原子替换某数据集缓存。
|
|
// 使用事务管道(MULTI/EXEC)依次执行 DEL + HSET + EXPIRE,对读者不可见中间态,刷新无空窗。
|
|
// items 的 key 为主键字符串,value 为任意可 json.Marshal 的对象;items 为空时仅清空该数据集。
|
|
func ReplaceAll(ctx context.Context, name string, items map[string]any, ttl time.Duration) (err error) {
|
|
key := redissys.RKey(name)
|
|
fields := make(map[string]any, len(items))
|
|
for f, v := range items {
|
|
var b []byte
|
|
if b, err = json.Marshal(v); err != nil {
|
|
return
|
|
}
|
|
fields[f] = b
|
|
}
|
|
pipe := redissys.Conn().TxPipeline()
|
|
pipe.Del(ctx, key)
|
|
if len(fields) > 0 {
|
|
pipe.HSet(ctx, key, fields)
|
|
if ttl > 0 {
|
|
pipe.Expire(ctx, key, ttl)
|
|
}
|
|
}
|
|
_, err = pipe.Exec(ctx)
|
|
return
|
|
}
|
|
|
|
// GetOne 按主键取单条;缓存中不存在该 field 时返回 (nil, false, nil)。
|
|
func GetOne[T any](ctx context.Context, name, field string) (v *T, found bool, err error) {
|
|
var b []byte
|
|
if b, err = redissys.Conn().HGet(ctx, redissys.RKey(name), field).Bytes(); err != nil {
|
|
if err == redis.Nil {
|
|
err = nil
|
|
}
|
|
return
|
|
}
|
|
v = new(T)
|
|
if err = json.Unmarshal(b, v); err != nil {
|
|
v = nil
|
|
return
|
|
}
|
|
found = true
|
|
return
|
|
}
|
|
|
|
// GetAll 取整个数据集;缓存为空时返回空切片。
|
|
func GetAll[T any](ctx context.Context, name string) (list []*T, err error) {
|
|
var m map[string]string
|
|
if m, err = redissys.Conn().HGetAll(ctx, redissys.RKey(name)).Result(); err != nil {
|
|
return
|
|
}
|
|
list = make([]*T, 0, len(m))
|
|
for _, s := range m {
|
|
v := new(T)
|
|
if err = json.Unmarshal([]byte(s), v); err != nil {
|
|
list = nil
|
|
return
|
|
}
|
|
list = append(list, v)
|
|
}
|
|
return
|
|
}
|
|
|