Skip to content

缓存

VEF Framework 提供了统一的缓存接口,支持内存缓存和 Redis 缓存。

缓存配置

yaml
# config.yaml
cache:
  driver: "redis"  # memory or redis
  prefix: "myapp:"
  defaultTTL: 300  # seconds

基本用法

获取缓存实例

go
import "github.com/ilxqx/vef-framework-go/cache"

// Get default cache instance
c := cache.Default()

// Get named cache instance
c := cache.Get("users")

设置和获取

go
// Set value with default TTL
err := c.Set("user:1", user)

// Set value with custom TTL
err := c.Set("user:1", user, cache.WithTTL(time.Hour))

// Get value
var user models.User
err := c.Get("user:1", &user)
if err == cache.ErrNotFound {
    // Key not found
}

删除缓存

go
// Delete single key
err := c.Delete("user:1")

// Delete multiple keys
err := c.DeleteMany("user:1", "user:2", "user:3")

// Delete by pattern
err := c.DeletePattern("user:*")

缓存模式

Remember 模式

go
// Get from cache or load from database
var user models.User
err := c.Remember("user:1", &user, time.Hour, func() (interface{}, error) {
    var u models.User
    err := orm.DB().First(&u, "id = ?", "1").Error
    return u, err
})

Forever 模式

go
// Cache without expiration
err := c.Forever("config:settings", settings)

缓存标签

使用标签管理缓存

go
// Set with tags
err := c.Set("user:1", user, cache.WithTags("users", "department:1"))

// Invalidate by tag
err := c.InvalidateTag("users")

// Invalidate multiple tags
err := c.InvalidateTags("users", "department:1")

分布式锁

使用缓存实现分布式锁

go
// Acquire lock
lock, err := c.Lock("order:process:123", time.Minute)
if err != nil {
    return errors.New("failed to acquire lock")
}
defer lock.Release()

// Critical section
processOrder("123")

带重试的锁

go
lock, err := c.LockWithRetry("order:process:123", time.Minute, cache.LockOptions{
    RetryCount: 3,
    RetryDelay: time.Second,
})

缓存预热

应用启动时预热

go
func WarmupCache(lc fx.Lifecycle, c cache.Cache) {
    lc.Append(fx.Hook{
        OnStart: func(ctx context.Context) error {
            // Load frequently accessed data
            var configs []models.Config
            orm.DB().Find(&configs)
            
            for _, cfg := range configs {
                c.Set(fmt.Sprintf("config:%s", cfg.Key), cfg.Value)
            }
            
            return nil
        },
    })
}

缓存统计

go
// Get cache statistics
stats := c.Stats()

fmt.Printf("Hits: %d\n", stats.Hits)
fmt.Printf("Misses: %d\n", stats.Misses)
fmt.Printf("Keys: %d\n", stats.Keys)
fmt.Printf("Size: %d bytes\n", stats.Size)

在 API 中使用缓存

go
type UserResource struct {
    api.Resource
    cache cache.Cache
}

func NewUserResource(c cache.Cache) api.Resource {
    return &UserResource{
        Resource: api.NewResource("smp/sys/user"),
        cache:    c,
    }
}

func (r *UserResource) GetUser(ctx fiber.Ctx, params struct {
    UserId string `json:"userId" validate:"required"`
}) error {
    cacheKey := fmt.Sprintf("user:%s", params.UserId)
    
    // Try cache first
    var user models.User
    err := r.cache.Get(cacheKey, &user)
    if err == nil {
        return api.Success(ctx, user)
    }
    
    // Load from database
    if err := orm.DB().First(&user, "id = ?", params.UserId).Error; err != nil {
        return api.NotFound(ctx, "User not found")
    }
    
    // Cache for 5 minutes
    r.cache.Set(cacheKey, user, cache.WithTTL(5*time.Minute))
    
    return api.Success(ctx, user)
}

下一步

基于 Apache License 2.0 许可发布