go-zero(十) 数据缓存和Redis使用

go zero Redis使用和数据缓存

一、创建带有缓存的model

1.生成代码

我们还是使用之前的user表,具体形式如下:

sql 复制代码
CREATE TABLE `users` (
	`id` BIGINT NOT NULL AUTO_INCREMENT,
	`username` VARCHAR(50) NOT NULL COLLATE 'utf8_general_ci',
	`password` VARCHAR(255) NOT NULL COLLATE 'utf8_general_ci',
	`created_at` TIMESTAMP NULL DEFAULT (CURRENT_TIMESTAMP),
	PRIMARY KEY (`id`) USING BTREE,
	UNIQUE INDEX `username` (`username`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;

现在我们可以通过goctl来生成一带有缓存的model:

bash 复制代码
goctl model mysql datasource -url="root:PXDN93VRKUm8TeE7@tcp(127.0.0.1:33069)/test_zero" -table="users" -dir ./model  -c  

-c 代表使用缓存

生成后我们把原来的model文件替换的掉,现在我们看下生成的代码:

go 复制代码
// NewUsersModel returns a model for the database table.
func NewUsersModel(conn sqlx.SqlConn, c cache.CacheConf, opts ...cache.Option) UsersModel {
	return &customUsersModel{
		defaultUsersModel: newUsersModel(conn, c, opts...),
	}
}

NewUsersModel 多了一个c cache.CacheConf cache参数

我们追踪下代码:

go 复制代码
type CacheConf = ClusterConf

接着追踪:

复制代码
type (
	// A ClusterConf is the config of a redis cluster that used as cache.
	ClusterConf []NodeConf

	// A NodeConf is the config of a redis node that used as cache.
	NodeConf struct {
		redis.RedisConf
		Weight int `json:",default=100"`
	}
)

通过上面两段代码可以看到 cache 其实就是 Redis

2. 使用Cache

先在yaml配置文件中,添加redis的配置信息:

复制代码
Cache: 
  - Host: "redisxxxxxx.redns.redis-cloud.com:16976"
    Pass: "lb8ZWuQwJENyzRiHUFjNnGJG0fgnKx5y"

接着修改config.go,在结构体中添加 cache:

go 复制代码
type Config struct {
	rest.RestConf
	/*
	....
	*/
	// 在结构体中增加cache
	Cache       cache.CacheConf
}

最后在servicecontext.go 中,修改NewUserModel的参数:

go 复制代码
type ServiceContext struct {
	Config          config.Config
	/*
	....
	*/
	
	UserModel       model.UserModel
	

}

func NewServiceContext(c config.Config) *ServiceContext {
	//mysql := NewMysql(c.MysqlDB.DbSource)
	return &ServiceContext{
		Config:        c,
		/*
		....
		*/
		UserModel:     model.NewUserModel(sqlx.NewMysql(c.MysqlDB.DbSource), c.Cache),
		
	}
}

3. 测试

现在我们运行项目测试一下:

我们登录账号后,可以看到redis里面多了一个信息:

二、 使用redis

刚刚我们介绍了cache,也知道了cache就是redis,现在来正式介绍下redis.

还是一样我们首先要配置redis

1. 配置redis

先在yaml配置文件中,添加redis的配置信息:

复制代码
RedisConfig:
- Host: "redisxxxxxx.redns.redis-cloud.com:16976"
  Pass: "lb8ZWuQwJENyzRiHUFjNnGJG0fgnKx5y

如果资源比较有限可以把redis 和cache用同一个配置,如果资源比较富裕可以分开使用。

接着修改config.go,在结构体中添加 redis配置:

go 复制代码
type Config struct {
	rest.RestConf
	/*
	....
	*/
	// 在结构体中增加redis配置
	RedisConfig redis.RedisConf
}

最后在servicecontext.go 中,添加redis:

go 复制代码
type ServiceContext struct {
	Config          config.Config
	/*
	....
	*/
	
	Redis           *redis.Redis
	

}

func NewServiceContext(c config.Config) *ServiceContext {
	//mysql := NewMysql(c.MysqlDB.DbSource)
	return &ServiceContext{
		Config:        c,
		/*
		....
		*/
		//使用MustNewRedis 链接redis
		Redis:         redis.MustNewRedis(c.RedisConfig),
	}
}

2. 使用redis 保存token

修改服务端代码,在登录实现token存储到redis中:

go 复制代码
func (l *LoginLogic) Login(in *pb.LoginReq) (*pb.LoginResp, error) {
	// todo: add your logic here and delete this line

	userModel := l.svcCtx.UserModel

	user, err := userModel.FindOneByUsername(l.ctx, in.Username)
	if err != nil && err != model.ErrNotFound {
		return nil, errors.New(0, "数据库连接失败")
	}

	//从配置文件中获取secret 、secret
	secret := l.svcCtx.Config.JwtAuth.AccessSecret
	expire := l.svcCtx.Config.JwtAuth.AccessExpire
	//生成jwt token
	token, err := getJwtToken(secret, time.Now().Unix(), expire, in.Username)
	if err != nil {
		return nil, errors.New(4, "token生成失败")
	}
	
	// 登录成功后将用户信息写入 Redis
	err = l.svcCtx.Redis.SetexCtx(l.ctx, fmt.Sprintf("token:%s", token), in.Username, int(expire))
	if err != nil {
		return nil, errors.New(66, "redis错误")
	}
	//查询username判断是否有数据
	if user != nil {
		//如果有数据,密码是否和数据库匹配
		if in.Password == user.Password {

			return &pb.LoginResp{
				Token: "Bearer " + token, //开头添加Bearer
			}, nil

		} else {
			return nil, errors.New(5, "密码错误")
		}
	} else {
		return nil, errors.New(6, "用户未注册")

	}
}

redis 的设置方法有几种,具体的可以看代码,我这里使用的是SetexCtx

3. 运行项目测试

可以看到token 成功的存储到了redis中

相关推荐
apocelipes9 小时前
从源码角度解析C++20新特性如何简化线程超时取消
c++·性能优化·golang·并发·c++20·linux编程
摇滚侠9 小时前
Redis 零基础到进阶,Redis 哨兵监控,笔记63-73
数据库·redis·笔记
程序员卷卷狗9 小时前
Redis事务与MySQL事务有什么区别?一文分清
数据库·redis·mysql
挺6的还9 小时前
5.string类型
redis
Li_76953214 小时前
Redis —— (五)
java·redis·后端·spring
hgz071014 小时前
Redis高级特性与生产环境部署
redis
共享家952715 小时前
Redis背景知识
数据库·redis·缓存
Rinai_R15 小时前
Go 的调度模型
开发语言·后端·golang
WongLeer16 小时前
Redis 学习笔记
redis·笔记·学习·redis缓存·redis发布订阅
挺6的还16 小时前
4.常用数据结构和单线程模型理解
redis