【Golang学习之旅】Go + Redis 缓存设计与优化(项目实战)
文章目录
- 业务需求
- 1. 缓存设计
- 2. Go+Redis代码实现
- 3. 代码解析
- 4. 性能优化
在本节中,我们将通过一个实际的项目案例,演示如何在 Go 中使用 Redis 实现高效的缓存设计与优化。
业务需求
假设我们正在开发一个电商平台,需要缓存商品信息以提高页面加载速度。商品信息经常被查询,但修改频率较低,因此使用 Redis 作为缓存会大大减少数据库的查询压力。
1. 缓存设计
缓存粒度
:我们将每个商品的信息作为一个缓存项进行存储,缓存的键为商品的 ID,值为商品的 JSON 数据。缓存失效策略
:设置缓存的过期时间为 10 分钟,这样商品信息会在 10 分钟后自动失效,防止过期数据的出现。缓存预热
:在系统启动时,我们通过预加载常见商品的数据到缓存中,减少首次访问时的缓存未命中的情况。
2. Go+Redis代码实现
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"time"
"github.com/go-redis/redis/v8"
)
var ctx = context.Background()
// 商品结构体
type Product struct {
ID string `json:"id"`
Name string `json:"name"`
Price float64 `json:"price"`
}
func getProductFromDB(productID string) (*Product, error) {
// 模拟从数据库获取商品数据
return &Product{
ID: productID,
Name: "Example Product",
Price: 99.99,
}, nil
}
func getProductFromCache(rdb *redis.Client, productID string) (*Product, error) {
// 从缓存中获取商品数据
val, err := rdb.Get(ctx, productID).Result()
if err == redis.Nil {
// 缓存未命中,查询数据库
return nil, nil
} else if err != nil {
return nil, err
}
var product Product
err = json.Unmarshal([]byte(val), &product)
if err != nil {
return nil, err
}
return &product, nil
}
func setProductToCache(rdb *redis.Client, product *Product) error {
// 将商品数据缓存到 Redis
productData, err := json.Marshal(product)
if err != nil {
return err
}
return rdb.Set(ctx, product.ID, productData, 10*time.Minute).Err()
}
func getProduct(rdb *redis.Client, productID string) (*Product, error) {
// 尝试从缓存中获取商品
product, err := getProductFromCache(rdb, productID)
if err != nil {
return nil, err
}
if product == nil {
// 缓存未命中,查询数据库并将结果缓存
product, err = getProductFromDB(productID)
if err != nil {
return nil, err
}
err = setProductToCache(rdb, product)
if err != nil {
return nil, err
}
}
return product, nil
}
func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379", // Redis 地址
Password: "", // 密码
DB: 0, // 默认数据库
})
// 获取商品
productID := "12345"
product, err := getProduct(rdb, productID)
if err != nil {
log.Fatalf("获取商品失败: %v", err)
}
fmt.Printf("商品信息: %+v\n", product)
}
3. 代码解析
获取商品信息
:首先,我们尝试从 Redis 缓存中获取商品信息。如果缓存未命中,我们会从数据库中查询商品数据,并将查询结果存入缓存。缓存设置过期时间
:商品信息被存入缓存时,我们设置了 10 分钟的过期时间,这样缓存会自动失效。缓存穿透与击穿防范
:通过合理的缓存失效时间和商品信息的缓存设计,避免了缓存穿透和缓存击穿的问题。
4. 性能优化
通过上述设计,我们显著减少了数据库查询次数,降低了数据库的负载,提高了系统的响应速度和吞吐量。