v0.1
This commit is contained in:
124
internal/infrastructure/cache/redis_cache.go
vendored
124
internal/infrastructure/cache/redis_cache.go
vendored
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
@@ -85,6 +86,7 @@ func (r *RedisCache) Set(ctx context.Context, key string, value interface{}, ttl
|
||||
|
||||
data, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
r.logger.Error("序列化缓存数据失败", zap.String("key", key), zap.Error(err))
|
||||
return fmt.Errorf("failed to marshal value: %w", err)
|
||||
}
|
||||
|
||||
@@ -106,10 +108,11 @@ func (r *RedisCache) Set(ctx context.Context, key string, value interface{}, ttl
|
||||
|
||||
err = r.client.Set(ctx, fullKey, data, expiration).Err()
|
||||
if err != nil {
|
||||
r.logger.Error("Failed to set cache", zap.String("key", key), zap.Error(err))
|
||||
r.logger.Error("设置缓存失败", zap.String("key", key), zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
r.logger.Debug("设置缓存成功", zap.String("key", key), zap.Duration("ttl", expiration))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -158,6 +161,7 @@ func (r *RedisCache) GetMultiple(ctx context.Context, keys []string) (map[string
|
||||
|
||||
values, err := r.client.MGet(ctx, fullKeys...).Result()
|
||||
if err != nil {
|
||||
r.logger.Error("批量获取缓存失败", zap.Strings("keys", keys), zap.Error(err))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -165,9 +169,15 @@ func (r *RedisCache) GetMultiple(ctx context.Context, keys []string) (map[string
|
||||
for i, val := range values {
|
||||
if val != nil {
|
||||
var data interface{}
|
||||
if err := json.Unmarshal([]byte(val.(string)), &data); err == nil {
|
||||
result[keys[i]] = data
|
||||
// 修复:改进JSON反序列化错误处理
|
||||
if err := json.Unmarshal([]byte(val.(string)), &data); err != nil {
|
||||
r.logger.Warn("反序列化缓存数据失败",
|
||||
zap.String("key", keys[i]),
|
||||
zap.String("value", val.(string)),
|
||||
zap.Error(err))
|
||||
continue
|
||||
}
|
||||
result[keys[i]] = data
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,17 +220,107 @@ func (r *RedisCache) SetMultiple(ctx context.Context, data map[string]interface{
|
||||
|
||||
// DeletePattern 按模式删除
|
||||
func (r *RedisCache) DeletePattern(ctx context.Context, pattern string) error {
|
||||
fullPattern := r.getFullKey(pattern)
|
||||
|
||||
keys, err := r.client.Keys(ctx, fullPattern).Result()
|
||||
if err != nil {
|
||||
return err
|
||||
// 修复:避免重复添加前缀
|
||||
var fullPattern string
|
||||
if strings.HasPrefix(pattern, r.prefix+":") {
|
||||
fullPattern = pattern
|
||||
} else {
|
||||
fullPattern = r.getFullKey(pattern)
|
||||
}
|
||||
|
||||
if len(keys) > 0 {
|
||||
return r.client.Del(ctx, keys...).Err()
|
||||
|
||||
// 检查上下文是否已取消
|
||||
if ctx.Err() != nil {
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
|
||||
var cursor uint64
|
||||
var totalDeleted int64
|
||||
maxIterations := 100 // 防止无限循环
|
||||
iteration := 0
|
||||
|
||||
for {
|
||||
// 检查迭代次数限制
|
||||
iteration++
|
||||
if iteration > maxIterations {
|
||||
r.logger.Warn("缓存删除操作达到最大迭代次数限制",
|
||||
zap.String("pattern", fullPattern),
|
||||
zap.Int("max_iterations", maxIterations),
|
||||
zap.Int64("total_deleted", totalDeleted),
|
||||
)
|
||||
break
|
||||
}
|
||||
|
||||
// 检查上下文是否已取消
|
||||
if ctx.Err() != nil {
|
||||
r.logger.Warn("缓存删除操作被取消",
|
||||
zap.String("pattern", fullPattern),
|
||||
zap.Int64("total_deleted", totalDeleted),
|
||||
zap.Error(ctx.Err()),
|
||||
)
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
// 执行SCAN操作
|
||||
keys, next, err := r.client.Scan(ctx, cursor, fullPattern, 1000).Result()
|
||||
if err != nil {
|
||||
// 如果是上下文取消错误,直接返回
|
||||
if err == context.Canceled || err == context.DeadlineExceeded {
|
||||
r.logger.Warn("缓存删除操作被取消",
|
||||
zap.String("pattern", fullPattern),
|
||||
zap.Int64("total_deleted", totalDeleted),
|
||||
zap.Error(err),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
r.logger.Error("扫描缓存键失败",
|
||||
zap.String("pattern", fullPattern),
|
||||
zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
// 批量删除找到的键
|
||||
if len(keys) > 0 {
|
||||
// 使用pipeline批量删除,提高性能
|
||||
pipe := r.client.Pipeline()
|
||||
pipe.Del(ctx, keys...)
|
||||
|
||||
cmds, err := pipe.Exec(ctx)
|
||||
if err != nil {
|
||||
r.logger.Error("批量删除缓存键失败",
|
||||
zap.Strings("keys", keys),
|
||||
zap.Error(err))
|
||||
return err
|
||||
}
|
||||
|
||||
// 统计删除的键数量
|
||||
for _, cmd := range cmds {
|
||||
if delCmd, ok := cmd.(*redis.IntCmd); ok {
|
||||
if deleted, err := delCmd.Result(); err == nil {
|
||||
totalDeleted += deleted
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r.logger.Debug("批量删除缓存键",
|
||||
zap.Strings("keys", keys),
|
||||
zap.Int("batch_size", len(keys)),
|
||||
zap.Int64("total_deleted", totalDeleted),
|
||||
)
|
||||
}
|
||||
|
||||
cursor = next
|
||||
if cursor == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
r.logger.Debug("缓存模式删除完成",
|
||||
zap.String("pattern", fullPattern),
|
||||
zap.Int64("total_deleted", totalDeleted),
|
||||
zap.Int("iterations", iteration),
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user