go 集成go-redis 缓存操作

news/2024/11/8 10:07:03 标签: 缓存, golang, redis

一、什么是Go Redis

这是一个流行的Go语言Redis客户端库,它提供了细化的API,对每个Redis命令的功能进行了封装,使得用户只需记住命令,具体的用法可以直接查看接口的声明,使用成本较低。go-redis对数据类型按照Redis底层的类型进行统一,编译时可以帮助检查参数类型,并且它的响应统一采用Result的接口返回,确保了返回参数类型的正确性,对用户更加友好。此外,go-redis还支持连接池、Pipeline和事务,以及发布订阅Pub/Sub和键空间通知等功能。

二、go-redis特性

  • 多种客户端

支持单机Redis Server、Redis Cluster、Redis Sentinel、Redis分片服务器

  • 数据类型

go-redis会根据不同的redis命令处理成指定的数据类型,不必进行繁琐的数据类型转换

  • 功能完善

go-redis支持管道(pipeline)、事务、pub/sub、Lua脚本、mock、分布式锁等功能

三、安装go-redis

go-redis/v9 (支持所有的 redis 版本)

go get github.com/redis/go-redis/v9

四、连接配置

go-redis支持多种连接方式,这里只展示一种

func InitRedis() *redis.Client {
	rdb := redis.NewClient(&redis.Options{
		Addr:     viper.GetString("db.redis.addr"),
		Password: viper.GetString("db.redis.pwd"), // 没有密码,默认值
		DB:       viper.GetInt("db.redis.db"),     // 默认DB 0
	})
	return rdb
}

五、入门

Context 上下文

go-redis 支持 Context,你可以使用它控制 超时 或者传递一些数据, 也可以 监控 go-redis 性能。

ctx := context.Background()

redis-命令">执行 Redis 命令

val, err := rdb.Get(ctx, "key").Result()
fmt.Println(val)

// 你也可以分别访问值和错误:

get := rdb.Get(ctx, "key")
fmt.Println(get.Val(), get.Err())

执行尚不支持的命令

可以使用 Do() 方法执行尚不支持或者任意命令:

val, err := rdb.Do(ctx, "get", "key").Result()
if err != nil {
	if err == redis.Nil {
		fmt.Println("key does not exists")
		return
	}
	panic(err)
}
fmt.Println(val.(string))

Do() 方法返回 Cmd 类型,你可以使用它获取你想要的类型:

// Text is a shortcut for get.Val().(string) with proper error handling.
val, err := rdb.Do(ctx, "get", "key").Text()
fmt.Println(val, err)

方法列表:

s, err := cmd.Text()
flag, err := cmd.Bool()

num, err := cmd.Int()
num, err := cmd.Int64()
num, err := cmd.Uint64()
num, err := cmd.Float32()
num, err := cmd.Float64()

ss, err := cmd.StringSlice()
ns, err := cmd.Int64Slice()
ns, err := cmd.Uint64Slice()
fs, err := cmd.Float32Slice()
fs, err := cmd.Float64Slice()
bs, err := cmd.BoolSlice()

redis-nil">redis.Nil

redis.Nil 是一种特殊的错误,严格意义上来说它并不是错误,而是代表一种状态,例如你使用 Get 命令获取 key 的值,当 key 不存在时,返回 redis.Nil。在其他比如 BLPOP 、 ZSCORE 也有类似的响应,你需要区分错误:

val, err := rdb.Get(ctx, "key").Result()
switch {
case err == redis.Nil:
	fmt.Println("key不存在")
case err != nil:
	fmt.Println("错误", err)
case val == "":
	fmt.Println("值是空字符串")
}

Conn

redis.Conn 是从连接池中取出的单个连接,除非你有特殊的需要,否则尽量不要使用它。你可以使用它向 redis 发送任何数据并读取 redis 的响应,当你使用完毕时,应该把它返回给 go-redis,否则连接池会永远丢失一个连接。

cn := rdb.Conn(ctx)
defer cn.Close()

if err := cn.ClientSetName(ctx, "myclient").Err(); err != nil {
	panic(err)
}

name, err := cn.ClientGetName(ctx).Result()
if err != nil {
	panic(err)
}
fmt.Println("client name", name)

连接池大小

go-redis 底层维护了一个连接池,不需要手动管理。默认情况下, go-redis 连接池大小为 runtime.GOMAXPROCS * 10,在大多数情况下默认值已经足够使用,且设置太大的连接池几乎没有什么用,可以在 配置项 中调整连接池数量:

rdb := redis.NewClient(&redis.Options{
    PoolSize: 1000,
})

超时

如果你使用 context.Context 处理超时,但也不要禁用 DialTimeout 、ReadTimeout 和 WriteTimeout ,因为 go-redis 会在不使用 context.Context 的情况下执行一些后台检查,这些检查依赖这些超时配置项。

请注意:net.Conn 依赖 Deadline 而不是 ctx 。

context.Context 的超时时间不要设置太短,因为当 context.Context超时,连接池无法确认连接是否还能正常使用,后面可能还会接收到数据,这样的连接不能被复用,只能丢弃并打开新的网络连接。在网络出现缓慢、丢包、redis 服务器执行消耗过多时间时, 将出现大量连接被丢弃、新建连接,这样连接池也就失去了意义,且情况会越来越恶化。

你可以查看 Go Context timeouts can be harmful (英文版) 这篇文章了解更多。

context 是一种控制超时的方式,但并不是所有场景都适用它。

Lua 脚本

var incrBy = redis.NewScript(`
local key = KEYS[1]
local change = ARGV[1]

local value = redis.call("GET", key)
if not value then
  value = 0
end

value = value + change
redis.call("SET", key, value)

return value
`)

运行脚本

keys := []string{"my_counter"}
values := []interface{}{+1}
num, err := incrBy.Run(ctx, rdb, keys, values...).Int()

Lua 和 Go 类型

下面是 Lua 和 Go 语言的类型对照表,Lua 的 number 是一个浮点型数字,用于存储整数和浮点数,在 Lua 中不区分整数和浮点数,但 Redis 总是将 Lua 数字转换为舍去小数部分的整数,例如 3.14 变成 3,如果要返回浮点值,将其作为字符串返回并用 Go 解析成 float64。

Lua returnGo interface{}
number (float64)int64 (舍弃小数)
stringstring
falseredis.Nil error
trueint64(1)
{ok = "status"}string("status")
{err = "error message"}errors.New("error message")
{"foo", "bar"}[]interface{}{"foo", "bar"}
{foo = "bar", bar = "baz"}[]interface{}{} (不支持)

更多探索

官网:Golang Redis客户端


http://www.niftyadmin.cn/n/5743721.html

相关文章

基于SSM(Spring + Spring MVC + MyBatis)框架的快递管理系统

基于SSM(Spring Spring MVC MyBatis)框架的快递管理系统是一个典型的Web应用程序,用于管理和跟踪快递包裹的信息。下面我将提供一个简单的案例程序概述,包括主要的功能模块和技术栈介绍。 项目概述 功能需求 用户管理&#x…

【hdfs】【hbase】【大数据技术基础】实践二 HBase Java API编程

实践二 HBase Java API编程 为什么可以写命令还要编写程序?自动化批量处理? 尽管我们可以通过HBase的shell命令行工具进行数据操作,但在实际的生产环境中,为了提高效率和实现自动化处理,我们通常需要编写程序来与HBa…

前端八股文(一)HTML 持续更新中。。。

html常见八股 1.src和href的区别? src: 用于js脚本,img、iframe、script等标签 加载时会阻塞主线程,将资源内容嵌入到当前标签所在的位置,将其指向的资源下载应用到文档内 href: 用于链接a、link等标签…

react->Antd->Table调整checkbox默认样式

checkbox默认不展示,hover此行时,出现checkbox,选中后不消失: hover前,设置透明边框; hover时,checkbox出现 选中后 代码块: .ant-checkbox {.ant-checkbox-inner {border: transparent;}}.ant…

基于YOLOv8 Web的安全帽佩戴识别检测系统的研究和设计,数据集+训练结果+Web源码

摘要 在工地,制造工厂,发电厂等地方,施工人佩戴安全帽能有效降低事故发生概率,在工业制造、发电等领域需要进行施工人员安全帽监测。目前大多数的 YOLO 模型还拘泥于公司、企业开发生产的具体产品中,大多数无编程基础…

DeFi 4.0峥嵘初现:主权金融时代的来临

近年来,Web3领域的创新似乎遇到了瓶颈,DeFi(去中心化金融)从热潮的巅峰逐渐进入了一个沉寂期。我们再也没有见到像DeFi Summer那样的行业兴奋,资本市场的动荡和Meme币的出现,似乎让人们忘记了曾经的区块链技…

解析Eureka的架构

1. 引言 1.1 Eureka的定义与背景 Eureka是由Netflix开发的一个RESTful服务,用于服务发现。它是微服务架构中的一个核心组件,主要用于管理服务的注册和发现。Eureka允许服务提供者注册自己的服务信息,同时也允许服务消费者查询可用的服务&am…

【AI技术】PaddleSpeech

【AI技术】PaddleSpeech 技术介绍优点缺点 部署基础环境的搭建分步详解国内镜像源切换所需环境1 g所需环境2 vim所需环境3 cuda所需环境4 cudnn所需环境5 ssl源码拉取PaddleSpeech环境安装 部署文件分享DockerHub 技术介绍 PaddleSpeech是飞浆平台的一款TTS框架。 优点 开源…