首页 > 数据库 >go-zero 使用 redis 作为 cache 的 2 种姿势

go-zero 使用 redis 作为 cache 的 2 种姿势

时间:2024-08-02 21:38:43浏览次数:11  
标签:err optional cache redis json zero go config

在 go-zero 框架内,如在 rpc 的应用 service 中,其内部已经预置了 redis 的应用,所以我们只需要在配置中加入相关字段即可,另外,在 svcContext 声明 redis client 后即可在具体的业务逻辑处理中应用。

但这里有个问题,如我用的是 go-zero 1.5.0 版本,从源码分析来看,redis 的连接并没用到 连接池,虽然在 go-zero/redis 已经为我们声明了足够的 redis 操作接口,但如果你有 连接池 的需求,还有另外一条路径,自己在应用中声明 连接池,但是具体的操作,也需要自己去写。

下面就从上面说的两个方面分享下 redis 的两种使用姿势吧。

框架内置的 redis

我们假设你已经生成了 rpc 的应用,然后接下来就是这样的一些主要工作:

  • 1.config.go 文件定义你的 redis 配置结构体并放入 config 结构体中, 由于 zrpc.RpcServerConf 含有 Redis 的定义,直接跳转下步
  • 2.yaml配置文件中,声明你的配置
  • 3.在 svcContext 加入 redisClient
  • 4.业务逻辑处理中加入 redis 作为缓存

完成以上,你就完成了通过框架内置的 redis 接口的使用。

定义你的 redis 结构体

internal/config/config.go

type Config struct {
	zrpc.RpcServerConf
}

go-zero/zrpc/config.go

// A RpcServerConf is a rpc server config.
type RpcServerConf struct {
		service.ServiceConf
		ListenOn      string
		Etcd          discov.EtcdConf    `json:",optional,inherit"`
		Auth          bool               `json:",optional"`
		Redis         redis.RedisKeyConf `json:",optional"`  // 这里就是预置的字段
		StrictControl bool               `json:",optional"`
		// setting 0 means no timeout
		Timeout      int64 `json:",default=2000"`
		CpuThreshold int64 `json:",default=900,range=[0:1000]"`
		// grpc health check switch
		Health      bool `json:",default=true"`
		Middlewares ServerMiddlewaresConf
	}

go-zero/core/stores/redis/conf.go

type (
	// A RedisConf is a redis config.
	RedisConf struct {
		Host string
		Type string `json:",default=node,options=node|cluster"`
		Pass string `json:",optional"`
		Tls  bool   `json:",optional"`
	}

	// A RedisKeyConf is a redis config with key.
	RedisKeyConf struct {
		RedisConf
		Key string `json:",optional"`
	}
)

声明配置

结合上面的内容,你只需要在 yaml 文件中注明下面内容:

Redis:
  Host: xx.xx.xx.xx:6379
  Type: node
  Tls: false

在 svcContext 加入 redisClient

直接看代码

package svc

import (
	"userrpcv1/internal/config"
    
    zeroRds "github.com/zeromicro/go-zero/core/stores/redis"
)

type ServiceContext struct {
	Config config.Config
	// claim ur redis client in here
	RedisClient *zeroRds.Redis
}

func NewServiceContext(c config.Config) *ServiceContext {
	//conf := c.Redis
	redisClient := zeroRds.MustNewRedis(conf.Redis)

	return &ServiceContext{
		Config: c,
		RedisClient: redisClient,
	}
}

业务逻辑应用

你的某个接口业务逻辑处理

    //logx.Info("Set Redis cache now")
	//err := l.svcCtx.RedisClient.Setex(fmt.Sprintf("Sum:%d:%d", in.A, in.B), fmt.Sprintf("Result:%d time:%v", sum, time.Now().Format(time.RFC3339)), ttl)
	//if err != nil {
	//	logx.Errorf("Rpc A9Sum set cache error: %v", err)
	//}

到这里你就成功了,直接拿去用吧。

通过自定义 redis 连接池

这里与上面有些不同,我们会自定义 redis 的结构体,自定义连接池的配置,自定义 client ,以及对应的一些操作,步骤如下:

  • 自定义 redis 配置结构体
  • yaml文件中声明配置信息
  • 编写连接池等的初始化
  • 编写连接池的接口
  • 业务逻辑处理中使用连接池

自定义 redis 配置结构体

依然还是你的 config.py 中加入以下:

package config

import "github.com/zeromicro/go-zero/rest"

type Config struct {
	rest.RestConf
	CacheConf CacheConf
}

type CacheConf struct {
	Password string `json:",optional"`
	Host     string `json:",optional"`
	Port     int64  `json:",optional"`
	DBName   int    `json:",optional"`

	MaxIdle     int   `json:",optional"`
	MaxActive   int   `json:",optional"`
	IdleTimeout int64 `json:",optional"`
}

yaml文件中声明配置信息

Name: limit
Host: 0.0.0.0
Port: 8888
MaxConns: 100000

CacheConf:
  Password: ""
  Host: 172.30.3.57
  Port: 6379
  DBName: 15
  MaxIdle: 2
  MaxActive: 5
  IdleTimeout: 1000000000

编写连接池等的初始化

package redis

import (
	"fmt"
	"math"
	"time"

	"demo24/micro_svc/zero-limit/internal/config"

	"github.com/gomodule/redigo/redis"
	"github.com/zeromicro/go-zero/core/logx"
)

var (
	pool   *redis.Pool
	client redis.Conn
)

func InitRedis(conf config.CacheConf) {
	pool = &redis.Pool{
		MaxActive:   conf.MaxActive,
		MaxIdle:     conf.MaxIdle,
		IdleTimeout: time.Duration(conf.IdleTimeout),
		Dial: func() (redis.Conn, error) {
			addr := fmt.Sprintf("%s:%s", conf.Host, conf.Port)
			conn, err := redis.Dial("tcp", addr, redis.DialDatabase(conf.DBName))
			if err != nil {
				logx.Errorf("Create redis pool conn failed, err: %v", err)
				return nil, err
			}

			return conn, nil
		},
	}

	client = pool.Get()
	_, err := redis.String(client.Do("ping"))
	if err != nil {
		logx.Errorf("redis conn pool init failed, err: %v.", err)
	}
}

编写连接池的接口

func GetRDB() redis.Conn {
	if pool == nil {
		logx.Errorf("get redis instance failed, err: pool is nil.")
		return nil
	}

	return pool.Get()
}

type Cache struct {
	client redis.Conn
}

func NewCache() *Cache {
	return &Cache{
		client: GetRDB(),
	}
}

func (cache *Cache) Set(key string, value interface{}, nx int) {
	if nx == 0 {
		nx = math.MaxInt32
	}
	_, err := cache.client.Do("SET", key, value, "NX", nx)
	if err != nil {
		logx.Errorf("set key failed, err: %v", err)
	}
}

func (cache *Cache) Get(key string) (val interface{}, err error) {
	value, err := cache.client.Do("GET", key)
	if err != nil {
		logx.Errorf("get cache err, err: %v", err)
		return nil, err
	}
	return value, nil
}

// TODO, u can implement ur cache operations

业务逻辑处理中使用连接池

...
    // redis pool
	//cache := redis.NewCache()
	//_, err = cache.Get(fmt.Sprintf("Sum:%d:%d", in.A, in.B))
	//if err != nil {
	//	logx.Errorf("Rpc A9Sum get cache error: %v", err)
	//}
...

通过以上流程,你可以实现这两种 go-zero 的使用 redis 作为缓存的方法,希望对你有用。

标签:err,optional,cache,redis,json,zero,go,config
From: https://www.cnblogs.com/davis12/p/18339658

相关文章

  • Redis学习[5] ——Redis过期删除和内存淘汰
    六、Redis过期键值删除6.1Redis的过期键值删除策略6.1.1什么是过期键值删除?Redis中是可以对key设置过期时间的,所以需要有相应的机制将已过期的键值对删除,也就是**过期键值删除策略。Redis会用一个过期字典(expiresdict)**来存储有过期时间的所有key。当查询一个key时,Red......
  • redis配置(不全)
    1、pom添加依赖<!--redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>2、Redis配置类packagecom.exam.config;importcom.......
  • PgStatement的executeCachedSql(String sql, int flags, String @Nullable [] column
    方法代码如下:privatebooleanexecuteCachedSql(Stringsql,intflags,String@Nullable[]columnNames)throwsSQLException{//第一部分PreferQueryModepreferQueryMode=connection.getPreferQueryMode();booleanshouldUseParameterized=false;......
  • Springboot Docker Redis Mysql集成
    尽管网上关于SpringbootDockerRedisMysql集成的文档很多,但是很多都是老文档,问题不少,所以我专门整理了这份文档。我家里的笔记本是mac,所以我就在mac上详细说明下我的搭建过程。首先我们需要安装docker,mac上本来就有docker的安装包,因此对于mac来说,安装docker就是一件比较轻松的......
  • 使用Redisson和分库分表技术实现海量请求注册功能
    文章目录1.海量注册的常见问题和解决方案概述2.布隆过滤器判断用户唯一性3.通过分布式锁和快速失败策略对同一时间的某一个账号进行锁定4.数据库唯一索引兜底5.通过水平分库水平分表配置分片规则6.通过自定义线程池和异步初始化配置线程池操作异步化1.海量......
  • redis-学习笔记一
    redis的常见数据类型及其使用场景常见的数据类型有五种:String字符串、List列表、Hash哈希、Set集合、Zset有序集合String字符串字符串是Redis中最基本的数据结构,可以存储任意类型的数据,包括文字、数字(整型、浮点等)等.它具有高效的读写操作和丰富的字符串处理函数,使用......
  • 【SpringBoot】集成Redis
    目录1redis1.1特点1.2支持的数据类型1.3应用场景2安装redis2.1docker3可视化软件3.1RedisDesktopManager(RDM)3.2QuickRedis(推荐)4SpringBoot集成4.1引入redis4.2.操作redis4.2.1直接操作4.3分布式会话场景(Resis-Session)1redis​ redis是一个用C语言开发的,基于内......
  • Redis和Mysql如何保持数据一致性
    一般情况下,Redis是用来实现应用和数据库之间读操作得缓存层,主要目的是减少数据库IO,还可以提升数据的IO性能。当应用程序需要去读取某个数据时,会首先尝试去Redis里面加载,如果命中就直接返回,如果没有命中,就去从数据库中查询,查询到数据之后再把这个数据缓存到Redis里。 如果一......
  • 7.Redis的Hash类型
    Hash类型,也叫散列,其value是一个无序字典,类似于HashMap结构。问题String结构是将对象序列化为json字符串后存储,当需要修改对象某个字段是不是很方便。key                            value(将java对象序列化为json......
  • 4.Redis数据结构&通用命令
    Redis数据结构Redis是一个键值对的数据库。key:大多都是Stringvalue:类型多种多样 Redis通用命令keys:查看所有的key不建议在生产环境上使用keys命令,因为redis是单线程的,keys命令会搜索很长一段时间,搜索的期间redis无法执行其他的命令,等于服务被阻塞了,影响redis的性......