文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

在 Go 项目中使用 Redis 的几个实用建议

2024-11-29 19:54

关注

需要过期的数据肯定是要存Redis的,比如用户的 token 之类的数据,否则存在数据库里还得写定时任务来实现token过期删除的功能 。

PS:Token 别用JWT,最好自己实现一套,后面会跟大家聊一些这方面的经验。

Redis 客户端的初始化

Redis 客户端的初始化,这个我建议还是在做好的Redis分层里通过 Go 自带的init 函数来实现初始化,别在整个项目的main方法里一个个调用自己定制化的 InitRedis 之类的方法去实现。

这个有人问为什么? 很简单因为Go的那些个init函数是在main方法之前执行的,就是被设计用来做初始化工作的。而且我们也不必担心初始化顺序的问题,被依赖地最深层次的包会最先被初始化。

package cache

......

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,
 })

 if err := redisClient.Ping(context.Background()).Err(); err != nil {
  // 连接不上redis 让项目停止启动
  panic(err)
 }
}

go-redis的客户端初始化完成后,如果不手动执行Ping 或者是其他Redis操作的话是不会真的去连接Redis服务器的,如果你希望在项目启动时尝试连接Redis服务器,失败则停止启动。那么就加一个Ping测试,连接不上用panic 让程序直接退出。

 if err := redisClient.Ping(context.Background()).Err(); err != nil {
  // 连接不上redis 让项目停止启动
  panic(err)
 }

当然如果你的程序有Redis连接不上读数据库的兜底策略,可以选择在项目启动的时候不进行Redis连接性的测试。

Redis Key 的命名Tips

我在项目中被 Redis 搞的头大最多的情况是,有的人特别喜欢在A项目里缓存了个什么数据,然后下游的B项目再去读这个数据,根据缓存里数据的状态执行不同的逻辑分支。

这个使用场景没问题,但是很多时候Redis 的 Key 携带的信息实在是太少,有的时候我在项目B里面DEBUG,查问题看到从Redis里读取到的数据跟预想的不一样,但是我在整个项目里也没发现这个缓存从哪存的。 这个时候如果你们团队的微服务拆地足够好(bushi,服务比人还多。。。。。。 会有当场去世的感觉。

别笑,项目比开发多是真事儿,因为以前50多人的团队造了10多个20多个项目,现在能给你缩减到5个人都不是怪事儿。

所以我们在使用Redis的时候,最好把Key 放在项目里统一的地方进行管理,同时在命名上加上包含业务、项目、模块信息的前缀名,通过它们在查问题的时候我们最起码能快速定位到缓存是哪个项目写进去的。

存结构化数据,用String 还是 Hash

用Redis时还有一个问题,就是很多时候我们的结构数据是JSON序列化后存到 Redis 的 String 类型中去的,Redis中还有Hash类型类似于编程语言里的哈希Map。

那么我们存储结构数据的时候应该存到 String 还是 Hash 中呢?答案是都行—— 仅从代码层面讲,哈哈哈......,但是前提是DAO查询方法返回做好明确的类型声明,像下面这样:

unc SetOrder(ctx context.Context, order *do.Order) error {
 jsonDataBytes, _ := json.Marshal(order)
 redisKey := fmt.Sprintf(enum.REDIS_KEY_ORDER_DETAIL, order.OrderNo)
 _, err := Redis().Set(ctx, redisKey, jsonDataBytes, 0).Result()
 if err != nil {
  log.New(ctx).Error("redis error", "err", err)
  return err
 }

 return nil
}

func GetOrder(ctx context.Context, orderNo string) (*do.Order, error) {
 redisKey := fmt.Sprintf(enum.REDIS_KEY_DEMO_ORDER_DETAIL, orderNo)
 jsonBytes, err := Redis().Get(ctx, redisKey).Bytes()
 if err != nil {
  log.New(ctx).Error("redis error", "err", err)
  return nil, err
 }
 data := new(do.Order)
 json.Unmarshal(jsonBytes, &data)
 return data, nil
}

如果你想从 Redis 层面把数据的结构化体现的更好一点,那么就用Hash,这里需要注意的是go-redis支持把结构体数据直接存到Redis Hash 的前提是要在结构体字段的tag 上携带 redis 标识。

这里有官方对这块的的解释。

Playing struct With "redis" tag. type MyHash struct { Key1 string `redis:"key1"`; Key2 int `redis:"key2"` }

HSet("myhash", MyHash{"value1", "value2"})

For struct, can be a structure pointer type, we only parse the field whose tag is redis. 

If you don't want the field to be read, you can use the `redis:"-"` flag to ignore it, or you don't need to set the redis tag. 

For the type of structure field, we only support simple data types: string, int/uint(8,16,32,64), float(32,64), time.Time(to RFC3339Nano), time.Duration(to Nanoseconds ), if you are other more complex or custom data types, please implement the encoding.BinaryMarshaler interface. 

所以我们的数据结构必须像下面这样定义:

type DummyOrder struct {
 OrderNo string `redis:"orderNo"`
 UserId  int64  `redis:"userId"`
}

然后go-redis 才能把数据通过HSET 存到Redis的Hash中,而直接读取Hash数据到比如上面定义的结构体的时候,需要用到go-redis 提供的HGetAll 和 Scan 方法,同理接受数据的结构体的字段也需要在tag中携带redis标识,不带这个标识Scan方法不会把数据填充到字段上。

总结

Redis的使用Tips上就先讲这么多,欢迎大家在评论区里补充,另外Go项目中用到redis时也有人会选择用redigo,我在工作时也用过,不过都是集成给我的一些老项目,不知道是不是redigo这个库出的时间更早。

来源:网管叨bi叨内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯