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

go zero Redis使用和数据缓存

一、创建带有缓存的model

1.生成代码

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

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:

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

-c 代表使用缓存

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

// 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参数

我们追踪下代码:

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:

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

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

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里面多了一个信息:

image.png

二、 使用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配置:

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

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

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中:

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中


image.png
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容