应用程序直接与缓存和数据库交互:
func GetUser(id int) (*User, error) { // 1. 先查缓存 val, err := redis.Get(ctx, fmt.Sprintf("user:%d", id)).Result() if err == nil { var user User json.Unmarshal([]byte(val), &user) return &user, nil } // 2. 缓存未命中,查数据库 user, err := db.QueryUser(id) if err != nil { return nil, err } // 3. 写入缓存 data, _ := json.Marshal(user) redis.Set(ctx, fmt.Sprintf("user:%d", id), data, 1*time.Hour) return user, nil }
缓存层负责从数据库加载:
type CacheLoader struct { redis *redis.Client db Database } func (c *CacheLoader) Get(key string) (interface{}, error) { // 尝试从缓存获取 val, err := c.redis.Get(ctx, key).Result() if err == nil { return val, nil } // 从数据库加载并缓存 data, err := c.db.Load(key) if err != nil { return nil, err } c.redis.Set(ctx, key, data, expireTime) return data, nil }
func UpdateUser(user *User) error { // 1. 更新数据库 err := db.UpdateUser(user) if err != nil { return err } // 2. 删除缓存 redis.Del(ctx, fmt.Sprintf("user:%d", user.ID)) return nil }
func UpdateUser(user *User) error { // 1. 删除缓存 redis.Del(ctx, fmt.Sprintf("user:%d", user.ID)) // 2. 更新数据库 err := db.UpdateUser(user) if err != nil { return err } // 3. 延迟删除缓存 go func() { time.Sleep(500 * time.Millisecond) redis.Del(ctx, fmt.Sprintf("user:%d", user.ID)) }() return nil }
func AcquireLock(key string, expiration time.Duration) (bool, error) { // 使用SET命令NX和EX选项 result, err := redis.SetNX(ctx, key, 1, expiration).Result() if err != nil { return false, err } return result, nil } func ReleaseLock(key string) error { // Lua脚本确保原子性 script := ` if redis.call("get", KEYS[1]) == 1 then return redis.call("del", KEYS[1]) else return 0 end ` _, err := redis.Eval(ctx, script, []string{key}).Result() return err }
type BloomFilter struct { bitset *big.Int funcs []hash.Hash64 } func (bf *BloomFilter) MightContain(data []byte) bool { for _, f := range bf.funcs { h := f.Sum64(data) if bf.bitset.Bit(int(h % uint64(bf.bitset.BitLen()))) == 0 { return false } } return true }
func GetProduct(id int) (*Product, error) { // 检查空值缓存 val, err := redis.Get(ctx, fmt.Sprintf("product_null:%d", id)).Result() if err == nil { return nil, ErrProductNotFound } // 正常查询逻辑... }
// 避免大量缓存同时过期 expireTime := baseExpire + time.Duration(rand.Intn(300))*time.Second redis.Set(ctx, key, value, expireTime)
// 本地缓存 + Redis func GetData(key string) (interface{}, error) { // L1:本地缓存 if val := localCache.Get(key); val != nil { return val, nil } // L2:Redis if val, err := redis.Get(ctx, key).Result(); err == nil { localCache.Set(key, val, 1*time.Minute) return val, nil } // L3:数据库 data, err := db.Query(key) if err != nil { return nil, err } redis.Set(ctx, key, data, 1*time.Hour) localCache.Set(key, data, 1*time.Minute) return data, nil }
pipe := redis.Pipeline() for i := 0; i < 100; i++ { pipe.Set(ctx, fmt.Sprintf("key:%d", i), i, 0) } _, err := pipe.Exec(ctx)
redis.NewClient(&redis.Options{ Addr: "localhost:6379", PoolSize: 100, MinIdleConns: 10, MaxRetries: 3, DialTimeout: 5 * time.Second, })
# 查看内存使用 INFO memory # 查看慢查询 SLOWLOG GET 10 # 查看连接数 INFO clients
关键指标: