Go语言实现分布式缓存:从Redis到多级缓存策略

发布时间:2026/5/20 18:21:05

Go语言实现分布式缓存:从Redis到多级缓存策略 Go语言实现分布式缓存从Redis到多级缓存策略引言缓存是提升应用性能的关键技术分布式缓存更是高并发系统的核心组件。Go语言提供了丰富的缓存客户端库支持Redis、Memcached等主流缓存系统。本文将深入探讨Go语言实现分布式缓存的实践。一、缓存基础1.1 缓存架构┌─────────────────────────────────────────────────────────────┐ │ 多级缓存架构 │ ├─────────────────────────────────────────────────────────────┤ │ Client │ L1 Cache │ L2 Cache │ DB │ │ ┌─────────┐ │ ┌─────────┐ │ ┌───────┐ │ │ │ │ 请求 │───────│─│ 内存缓存 │──│─│ Redis │───│── │ │ └─────────┘ │ └─────────┘ │ └───────┘ │ │ │ │ (本地缓存) │ (分布式) │ │ └─────────────────────────────────────────────────────────────┘1.2 缓存策略对比策略说明适用场景LRU最近最少使用热点数据缓存LFU最不经常使用访问频率预测FIFO先进先出时序数据TTL时间过期时效性数据写穿透写缓存同时写DB数据一致性要求高写回先写缓存后异步写DB写频繁场景二、Redis缓存实战2.1 安装依赖go get github.com/go-redis/redis/v82.2 客户端配置package cache import ( context time github.com/go-redis/redis/v8 ) type RedisCache struct { client *redis.Client } func NewRedisCache(addr, password string, db int) *RedisCache { client : redis.NewClient(redis.Options{ Addr: addr, Password: password, DB: db, PoolSize: 10, ReadTimeout: 5 * time.Second, WriteTimeout: 5 * time.Second, }) return RedisCache{client: client} } func (c *RedisCache) Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error { return c.client.Set(ctx, key, value, ttl).Err() } func (c *RedisCache) Get(ctx context.Context, key string) (string, error) { return c.client.Get(ctx, key).Result() } func (c *RedisCache) Delete(ctx context.Context, key string) error { return c.client.Del(ctx, key).Err() }2.3 缓存序列化import ( encoding/json ) func (c *RedisCache) SetStruct(ctx context.Context, key string, value interface{}, ttl time.Duration) error { data, err : json.Marshal(value) if err ! nil { return err } return c.client.Set(ctx, key, data, ttl).Err() } func (c *RedisCache) GetStruct(ctx context.Context, key string, dest interface{}) error { data, err : c.client.Get(ctx, key).Bytes() if err ! nil { return err } return json.Unmarshal(data, dest) }2.4 分布式锁func (c *RedisCache) Lock(ctx context.Context, key string, ttl time.Duration) (bool, error) { result, err : c.client.SetNX(ctx, key, locked, ttl).Result() if err ! nil { return false, err } return result, nil } func (c *RedisCache) Unlock(ctx context.Context, key string) error { return c.client.Del(ctx, key).Err() }三、本地缓存3.1 LRU缓存go get github.com/hashicorp/golang-lru/v2import ( github.com/hashicorp/golang-lru/v2 ) type LocalCache struct { cache *lru.Cache[string, interface{}] } func NewLocalCache(size int) (*LocalCache, error) { cache, err : lru.New[string, interface{}](size) if err ! nil { return nil, err } return LocalCache{cache: cache}, nil } func (c *LocalCache) Get(key string) (interface{}, bool) { return c.cache.Get(key) } func (c *LocalCache) Set(key string, value interface{}) { c.cache.Add(key, value) } func (c *LocalCache) Remove(key string) { c.cache.Remove(key) }3.2 多级缓存type MultiLevelCache struct { local *LocalCache remote *RedisCache } func NewMultiLevelCache(localSize int, redisAddr, redisPassword string, redisDB int) (*MultiLevelCache, error) { local, err : NewLocalCache(localSize) if err ! nil { return nil, err } remote : NewRedisCache(redisAddr, redisPassword, redisDB) return MultiLevelCache{ local: local, remote: remote, }, nil } func (c *MultiLevelCache) Get(ctx context.Context, key string) (interface{}, error) { // 先查本地缓存 if value, ok : c.local.Get(key); ok { return value, nil } // 再查远程缓存 var result interface{} err : c.remote.GetStruct(ctx, key, result) if err ! nil { return nil, err } // 写入本地缓存 c.local.Set(key, result) return result, nil } func (c *MultiLevelCache) Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error { // 同时更新两级缓存 c.local.Set(key, value) return c.remote.SetStruct(ctx, key, value, ttl) } func (c *MultiLevelCache) Delete(ctx context.Context, key string) error { c.local.Remove(key) return c.remote.Delete(ctx, key) }四、缓存策略4.1 缓存击穿处理func (c *MultiLevelCache) GetWithFallback(ctx context.Context, key string, fallback func() (interface{}, error), ttl time.Duration) (interface{}, error) { // 先尝试获取缓存 if value, err : c.Get(ctx, key); err nil { return value, nil } // 获取分布式锁 lockKey : key :lock locked, err : c.remote.Lock(ctx, lockKey, 5*time.Second) if err ! nil { return nil, err } // 如果没获取到锁等待后重试 if !locked { time.Sleep(100 * time.Millisecond) return c.Get(ctx, key) } defer c.remote.Unlock(ctx, lockKey) // 执行fallback value, err : fallback() if err ! nil { return nil, err } // 更新缓存 c.Set(ctx, key, value, ttl) return value, nil }4.2 缓存预热func (c *MultiLevelCache) Warmup(ctx context.Context, keys []string, fetcher func(string) (interface{}, error), ttl time.Duration) error { var wg sync.WaitGroup errChan : make(chan error, len(keys)) for _, key : range keys { wg.Add(1) go func(k string) { defer wg.Done() value, err : fetcher(k) if err ! nil { errChan - err return } if err : c.Set(ctx, k, value, ttl); err ! nil { errChan - err } }(key) } wg.Wait() close(errChan) for err : range errChan { if err ! nil { return err } } return nil }4.3 缓存淘汰策略type SmartCache struct { cache *MultiLevelCache metrics *CacheMetrics minHitRate float64 } func (sc *SmartCache) Get(ctx context.Context, key string) (interface{}, error) { sc.metrics.RecordRequest() value, err : sc.cache.Get(ctx, key) if err ! nil { sc.metrics.RecordMiss() return nil, err } sc.metrics.RecordHit() // 动态调整缓存策略 if sc.metrics.HitRate() sc.minHitRate { sc.optimizeCache() } return value, nil } func (sc *SmartCache) optimizeCache() { // 根据命中率动态调整缓存策略 // 例如降低TTL、增加缓存大小等 }五、缓存一致性5.1 写穿透模式func (c *MultiLevelCache) WriteThrough(ctx context.Context, key string, value interface{}, ttl time.Duration, dbWriter func(interface{}) error) error { // 先写数据库 if err : dbWriter(value); err ! nil { return err } // 再写缓存 return c.Set(ctx, key, value, ttl) }5.2 写回模式type WriteBackCache struct { cache *MultiLevelCache dirtyKeys map[string]bool flushInterval time.Duration dbWriter func(string, interface{}) error mu sync.Mutex } func (c *WriteBackCache) Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error { c.mu.Lock() c.dirtyKeys[key] true c.mu.Unlock() return c.cache.Set(ctx, key, value, ttl) } func (c *WriteBackCache) startFlushLoop() { ticker : time.NewTicker(c.flushInterval) defer ticker.Stop() for range ticker.C { c.flushDirty() } } func (c *WriteBackCache) flushDirty() { c.mu.Lock() dirtyKeys : make([]string, 0, len(c.dirtyKeys)) for key : range c.dirtyKeys { dirtyKeys append(dirtyKeys, key) delete(c.dirtyKeys, key) } c.mu.Unlock() for _, key : range dirtyKeys { value, err : c.cache.Get(context.Background(), key) if err ! nil { continue } c.dbWriter(key, value) } }六、实战高性能缓存服务type CacheService struct { cache *MultiLevelCache logger *zap.Logger metrics *CacheMetrics } func NewCacheService(config CacheConfig) (*CacheService, error) { cache, err : NewMultiLevelCache( config.LocalSize, config.RedisAddr, config.RedisPassword, config.RedisDB, ) if err ! nil { return nil, err } return CacheService{ cache: cache, logger: zap.L(), metrics: NewCacheMetrics(), }, nil } func (s *CacheService) Get(ctx context.Context, key string) (interface{}, error) { return s.cache.Get(ctx, key) } func (s *CacheService) Set(ctx context.Context, key string, value interface{}, ttl time.Duration) error { return s.cache.Set(ctx, key, value, ttl) } func (s *CacheService) Delete(ctx context.Context, key string) error { return s.cache.Delete(ctx, key) } func (s *CacheService) Warmup(ctx context.Context, keys []string, fetcher func(string) (interface{}, error), ttl time.Duration) error { return s.cache.Warmup(ctx, keys, fetcher, ttl) }结论分布式缓存是提升应用性能的关键技术Go语言提供了丰富的缓存客户端库支持各种缓存系统。通过合理设计多级缓存架构、选择合适的缓存策略、保证缓存一致性可以构建高性能的缓存服务。在实际项目中需要根据业务需求选择合适的缓存方案平衡性能和一致性要求。

相关新闻