缓存
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)
}