本节我们在项目中安装和集成 go-redis,让项目能访问Redis,后面实战项目中的用户认证体系会依赖Redis来实现,像Token、Session这些都是在Redis中存储的。
本节大纲如下:
图片
Redis的使用场景有不少,不过有一点需要提醒的是别把Redis当数据库用哦。
这里分享一篇 Redis应用场景汇总,里面罗列了十几个场景,大家有兴趣的可以看一下。
go-redis 的安装和配置
在我们的Go项目里访问Redis使用的是 go-redis 这个包,之前也见过一些项目使用redigo 来访问Redis,不过redigo已经停止维护了,所以就不考虑使用它了。
安装 go-redis 使用以下命令
go get github.com/redis/go-redis/v9
安装过程中会向项目依赖中添加下面这些包,在gomod 文件中也会看到它们的身影。
图片
依赖下载完成后,我们先不着急去初始化它,还是先把相关的配置先在配置文件里写好。在 applicaiton.dev.yaml 增加Redis相关配置。
redis: # 记得更改成自己的连接配置
addr: 127.0.0.1:31379
password: 123456
pool_size: 10
db: 0
其他两个环境的配置文件建议也先加上,避免配置文件之间结构和字段相差太多,等有测试和生产环境后再把配置调整过去即可。
配置添加完后,我们在 config.go 中增加 Redis 这些配置字段的对应的类型定义
var (
...
Redis *redisConfig
)
// Redis 配置
type redisConfig struct {
Addr string `mapstructure:"addr"`
Password string `mapstructure:"password"`
PoolSize int `mapstructure:"pool_size"`
DB int `mapstructure:"db"`
}
同时也在 bootstrap.go 中把config文件中的redis配置字段映射到 redisConfig 类型的变量 config.Redis上
func init() {
env := os.Getenv("ENV")
vp := viper.New()
...
vp.UnmarshalKey("redis", &Redis)
}
配置做好后,接下来我们在 dal/cache 目录中新建redisinit.go 文件,在其中对go-redis客户端进行初始化
var redisClient *redis.Client
func Redis() *redis.Client {
return redisClient
}
func init() {
redisClient = redis.NewClient(&redis.Options{
Addr: config.Redis.Addr,
Password: config.Redis.Password,
DB: config.Redis.DB,
PoolSize: config.Redis.PoolSize,
DialTimeout: 10 * time.Second,
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
PoolTimeout: 30 * time.Second,
})
if err :=redisClient.Ping(context.Background()).Err(); err != nil {
// 连接不上redis 让项目停止启动
panic(err)
}}
跟初始化GORM时一样,如果你不想用Go的init机制,这里可以把这个初始化方法修改名成InitRedis,到main函数中去调用它来手动完成初始化。
Redis Key 的管理
我们在使用Redis的时候,最好把Key 放在项目里统一的地方进行管理,同时在命名时给Key加上包含业务、项目、模块信息的前缀名,通过签证在查问题的时候我们最起码能快速定位到缓存是哪个项目写进去的。
我在平时维护项目中被 Redis 搞的头大的大部分情况是,很多旧代码在A项目里缓存了个什么数据,然后到下游的B项目再去读这个数据,根据缓存里数据的状态执行不同的逻辑分支。
有的时候监控系统报告B项目出了Bug,查问题看到从Redis里读取到的数据跟预想的不一样,一般人都会先在B项目中Debug,看下缓存设置的程序是不是有问题,但是针对这种情况把整个B项目搜遍也没发现缓存是从哪里存进去的。
所以 Redis Key 的命名不能太随意,最好包含设置缓存的项目名、所属业务等能确定缓存来源的信息。
我们在项目的 common/enum 目录中新增rediskey.go 在其中对Redis 缓存的 Key 进行统一管理
/ Redis Key的格式为:
// 项目名:模块名:键名
const (
REDIS_KEY_DEMO_ORDER_DETAIL = "GOMALL:DEMO:ORDER_DETAIL_%s"
)
这里先定义一个测试用的Redis缓存的键名。
- GOMALL:DEMO:ORDER_DETAIL_%s
Key的格式为 项目名:模块名:键名,你的公司大的话还可以在最前面加一个业务名,免得项目名重复了。
项目名:GOMALL
模块名:DEMO (因为是演示,正常情况下是ORDER、USER 这种模块名)
键名:ORDER_DETAIL_%s
在使用到这个 Redis 缓存的方法中可以来拿业务标识(比如订单号) 拼装出完整的Redis Key
redisKey := fmt.Sprintf(enum.REDIS_KEY_DEMO_ORDER_DETAIL, demoOrder.OrderNo)
Redis怎么做日志链路追踪
和在项目中集成ORM使用数据库时一样,除了关注常规的功能外,我们还要关注组件集成进项目后的可观测性。最基础的保障观测性的方式是组件日志整合到应用日志,并且通过traceId、reqeustId等方式讲它们归因到对应的请求上。