Golang微服务缓存机制探讨
Golang微服务缓存机制探讨 在 Go 微服务中我们将进行何种缓存。该服务将从 Oracle 数据库拉取记录。
2 回复
更多关于Golang微服务缓存机制探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go微服务中实现缓存机制时,通常采用多级缓存策略以提高性能并减轻数据库压力。以下是针对Oracle数据库的几种常见缓存方案及示例代码:
1. 内存缓存(使用sync.Map或第三方库)
import (
"sync"
"time"
)
type CacheItem struct {
Value interface{}
Expiration int64
}
type MemoryCache struct {
items sync.Map
mu sync.RWMutex
}
func (c *MemoryCache) Set(key string, value interface{}, duration time.Duration) {
expiration := time.Now().Add(duration).UnixNano()
c.items.Store(key, CacheItem{
Value: value,
Expiration: expiration,
})
}
func (c *MemoryCache) Get(key string) (interface{}, bool) {
item, found := c.items.Load(key)
if !found {
return nil, false
}
cacheItem := item.(CacheItem)
if time.Now().UnixNano() > cacheItem.Expiration {
c.items.Delete(key)
return nil, false
}
return cacheItem.Value, true
}
2. Redis分布式缓存
import (
"context"
"encoding/json"
"github.com/go-redis/redis/v8"
"time"
)
type RedisCache struct {
client *redis.Client
ctx context.Context
}
func NewRedisCache(addr string) *RedisCache {
return &RedisCache{
client: redis.NewClient(&redis.Options{
Addr: addr,
}),
ctx: context.Background(),
}
}
func (rc *RedisCache) Set(key string, value interface{}, expiration time.Duration) error {
jsonData, err := json.Marshal(value)
if err != nil {
return err
}
return rc.client.Set(rc.ctx, key, jsonData, expiration).Err()
}
func (rc *RedisCache) Get(key string, dest interface{}) error {
data, err := rc.client.Get(rc.ctx, key).Bytes()
if err != nil {
return err
}
return json.Unmarshal(data, dest)
}
3. 数据库查询结果缓存示例
type UserService struct {
db *sql.DB
cache *MemoryCache
}
func (s *UserService) GetUserByID(userID string) (*User, error) {
// 先尝试从缓存获取
if cached, found := s.cache.Get("user_" + userID); found {
return cached.(*User), nil
}
// 缓存未命中,查询数据库
var user User
query := `SELECT id, name, email FROM users WHERE id = :1`
err := s.db.QueryRow(query, userID).Scan(&user.ID, &user.Name, &user.Email)
if err != nil {
return nil, err
}
// 存入缓存,设置5分钟过期
s.cache.Set("user_"+userID, &user, 5*time.Minute)
return &user, nil
}
4. 缓存穿透防护(布隆过滤器实现)
import "github.com/bits-and-blooms/bloom/v3"
type BloomFilterCache struct {
filter *bloom.BloomFilter
cache *MemoryCache
}
func NewBloomFilterCache() *BloomFilterCache {
return &BloomFilterCache{
filter: bloom.NewWithEstimates(1000000, 0.01),
cache: &MemoryCache{},
}
}
func (bfc *BloomFilterCache) GetWithProtection(key string) (interface{}, bool) {
// 先检查布隆过滤器
if !bfc.filter.TestString(key) {
return nil, false
}
// 再检查实际缓存
return bfc.cache.Get(key)
}
5. 缓存预热机制
func (s *UserService) WarmUpCache() {
rows, err := s.db.Query("SELECT id, name, email FROM users WHERE active = 1")
if err != nil {
return
}
defer rows.Close()
for rows.Next() {
var user User
rows.Scan(&user.ID, &user.Name, &user.Email)
s.cache.Set("user_"+user.ID, &user, 30*time.Minute)
}
}
这些方案可根据实际场景组合使用。内存缓存适合高频访问的少量数据,Redis适合分布式环境下的数据共享,布隆过滤器能有效防止缓存穿透。对于Oracle数据库,建议在服务启动时进行缓存预热,并在数据更新时实现缓存失效策略。

