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中

相关推荐
forestsea1 小时前
深入理解Redisson RLocalCachedMap:本地缓存过期策略全解析
redis·缓存·redisson
佛祖让我来巡山1 小时前
Redis 为什么这么快?——「极速快递站」的故事
redis·redis为什么快?
啦啦啦_99993 小时前
Redis-0-业务逻辑
数据库·redis·缓存
自不量力的A同学4 小时前
Redisson 4.2.0 发布,官方推荐的 Redis 客户端
数据库·redis·缓存
fengxin_rou4 小时前
[Redis从零到精通|第四篇]:缓存穿透、雪崩、击穿
java·redis·缓存·mybatis·idea·多线程
fengxin_rou4 小时前
黑马点评实战篇|第二篇:商户查询缓存
缓存
是阿楷啊5 小时前
Java大厂面试场景:音视频场景中的Spring Boot与微服务实战
spring boot·redis·spring cloud·微服务·grafana·prometheus·java面试
笨蛋不要掉眼泪5 小时前
Redis哨兵机制全解析:原理、配置与实战故障转移演示
java·数据库·redis·缓存·bootstrap
ALex_zry17 小时前
Redis Cluster 分布式缓存架构设计与实践
redis·分布式·缓存
乔江seven20 小时前
【Flask 进阶】3 从同步到异步:基于 Redis 任务队列解决 API 高并发与长耗时任务阻塞
redis·python·flask