签入版本

This commit is contained in:
小蚂蚁云
2026-10-20 19:07:36 +08:00
commit 1b9bdac12f
882 changed files with 106953 additions and 0 deletions
+118
View File
@@ -0,0 +1,118 @@
package cache
import (
"context"
"sync/atomic"
"time"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcache"
)
// 统一缓存门面:Redis 优先(g.Redis,配置读取 manifest/config 的 redis 节),
// Redis 不可用时自动降级为进程内存(gcache),保证单机开发可用。
var memFallback atomic.Bool
// Init 探测 Redis 连通性,失败则切换内存模式
func Init(ctx context.Context) {
if _, err := g.Redis().Do(ctx, "PING"); err != nil {
memFallback.Store(true)
g.Log().Warningf(ctx, "Redis 不可用(%v),缓存降级为进程内存模式", err)
return
}
g.Log().Info(ctx, "Redis 缓存已连接")
}
// UsingMemory 是否处于内存降级模式
func UsingMemory() bool { return memFallback.Load() }
// Set 写入缓存(ttlSeconds<=0 表示不过期)
func Set(ctx context.Context, key, value string, ttlSeconds int) error {
if !memFallback.Load() {
var err error
if ttlSeconds > 0 {
_, err = g.Redis().Do(ctx, "SETEX", key, ttlSeconds, value)
} else {
_, err = g.Redis().Do(ctx, "SET", key, value)
}
if err == nil {
return nil
}
memFallback.Store(true)
g.Log().Warningf(ctx, "Redis 写入失败(%v),缓存降级为内存模式", err)
}
if ttlSeconds > 0 {
return gcache.Set(ctx, key, value, time.Duration(ttlSeconds)*time.Second)
}
return gcache.Set(ctx, key, value, -1)
}
// Get 读取缓存;第二个返回值表示是否存在
func Get(ctx context.Context, key string) (string, bool) {
if !memFallback.Load() {
v, err := g.Redis().Do(ctx, "GET", key)
if err == nil {
if v.IsNil() {
return "", false
}
return v.String(), true
}
memFallback.Store(true)
g.Log().Warningf(ctx, "Redis 读取失败(%v),缓存降级为内存模式", err)
}
v, err := gcache.Get(ctx, key)
if err != nil || v.IsNil() {
return "", false
}
return v.String(), true
}
// Del 删除缓存
func Del(ctx context.Context, keys ...string) error {
if len(keys) == 0 {
return nil
}
if !memFallback.Load() {
args := make([]any, 0, len(keys))
for _, k := range keys {
args = append(args, k)
}
if _, err := g.Redis().Do(ctx, "DEL", args...); err == nil {
return nil
}
}
for _, k := range keys {
_, _ = gcache.Remove(ctx, k)
}
return nil
}
// Exists 判断键是否存在
func Exists(ctx context.Context, key string) bool {
if !memFallback.Load() {
v, err := g.Redis().Do(ctx, "EXISTS", key)
if err == nil {
return v.Int() > 0
}
}
ok, err := gcache.Contains(ctx, key)
if err != nil {
return false
}
return ok
}
// SetNX 不存在时写入(防重复提交),成功返回 true
func SetNX(ctx context.Context, key, value string, ttlSeconds int) bool {
if !memFallback.Load() {
v, err := g.Redis().Do(ctx, "SET", key, value, "NX", "EX", ttlSeconds)
if err == nil {
return !v.IsNil() && v.String() == "OK"
}
}
if Exists(ctx, key) {
return false
}
_ = Set(ctx, key, value, ttlSeconds)
return true
}