go操作redis
go操作redis
依赖
go get github.com/redis/go-redis/v9
配置信息
/**
type Options struct {
// 连接网络类型,如: tcp、udp、unix等方式
// 如果为空默认tcp
Network string
// redis服务器地址,ip:port格式,比如:192.168.1.100:6379
// 默认为 :6379
Addr string
// ClientName 是对网络连接设置一个名字,使用 "CLIENT LIST" 命令
// 可以查看redis服务器当前的网络连接列表
// 如果设置了ClientName,go-redis对每个连接调用 `CLIENT SETNAME ClientName` 命令
// 查看: https://redis.io/commands/client-setname/
// 默认为空,不设置客户端名称
ClientName string
// 如果你想自定义连接网络的方式,可以自定义 `Dialer` 方法,
// 如果不指定,将使用默认的方式进行网络连接 `redis.NewDialer`
Dialer func(ctx context.Context, network, addr string) (net.Conn, error)
// 建立了新连接时调用此函数
// 默认为nil
OnConnect func(ctx context.Context, cn *Conn) error
// 当redis服务器版本在6.0以上时,作为ACL认证信息配合密码一起使用,
// ACL是redis 6.0以上版本提供的认证功能,6.0以下版本仅支持密码认证。
// 默认为空,不进行认证。
Username string
// 当redis服务器版本在6.0以上时,作为ACL认证信息配合密码一起使用,
// 当redis服务器版本在6.0以下时,仅作为密码认证。
// ACL是redis 6.0以上版本提供的认证功能,6.0以下版本仅支持密码认证。
// 默认为空,不进行认证。
Password string
// 允许动态设置用户名和密码,go-redis在进行网络连接时会获取用户名和密码,
// 这对一些认证鉴权有时效性的系统来说很有用,比如一些云服务商提供认证信息有效期为12小时。
// 默认为nil
CredentialsProvider func() (username string, password string)
// redis DB 数据库,默认为0
DB int
// 命令最大重试次数, 默认为3
MaxRetries int
// 每次重试最小间隔时间
// 默认 8 * time.Millisecond (8毫秒) ,设置-1为禁用
MinRetryBackoff time.Duration
// 每次重试最大间隔时间
// 默认 512 * time.Millisecond (512毫秒) ,设置-1为禁用
MaxRetryBackoff time.Duration
// 建立新网络连接时的超时时间
// 默认5秒
DialTimeout time.Duration
// 从网络连接中读取数据超时时间,可能的值:
// 0 - 默认值,3秒
// -1 - 无超时,无限期的阻塞
// -2 - 不进行超时设置,不调用 SetReadDeadline 方法
ReadTimeout time.Duration
// 把数据写入网络连接的超时时间,可能的值:
// 0 - 默认值,3秒
// -1 - 无超时,无限期的阻塞
// -2 - 不进行超时设置,不调用 SetWriteDeadline 方法
WriteTimeout time.Duration
// 是否使用context.Context的上下文截止时间,
// 有些情况下,context.Context的超时可能带来问题。
// 默认不使用
ContextTimeoutEnabled bool
// 连接池的类型,有 LIFO 和 FIFO 两种模式,
// PoolFIFO 为 false 时使用 LIFO 模式,为 true 使用 FIFO 模式。
// 当一个连接使用完毕时会把连接归还给连接池,连接池会把连接放入队尾,
// LIFO 模式时,每次取空闲连接会从"队尾"取,就是刚放入队尾的空闲连接,
// 也就是说 LIFO 每次使用的都是热连接,连接池有机会关闭"队头"的长期空闲连接,
// 并且从概率上,刚放入的热连接健康状态会更好;
// 而 FIFO 模式则相反,每次取空闲连接会从"队头"取,相比较于 LIFO 模式,
// 会使整个连接池的连接使用更加平均,有点类似于负载均衡寻轮模式,会循环的使用
// 连接池的所有连接,如果你使用 go-redis 当做代理让后端 redis 节点负载更平均的话,
// FIFO 模式对你很有用。
// 如果你不确定使用什么模式,请保持默认 PoolFIFO = false
PoolFIFO bool
// 连接池最大连接数量,注意:这里不包括 pub/sub,pub/sub 将使用独立的网络连接
// 默认为 10 * runtime.GOMAXPROCS
PoolSize int
// PoolTimeout 代表如果连接池所有连接都在使用中,等待获取连接时间,超时将返回错误
// 默认是 1秒+ReadTimeout
PoolTimeout time.Duration
// 连接池保持的最小空闲连接数,它受到PoolSize的限制
// 默认为0,不保持
MinIdleConns int
// 连接池保持的最大空闲连接数,多余的空闲连接将被关闭
// 默认为0,不限制
MaxIdleConns int
// ConnMaxIdleTime 是最大空闲时间,超过这个时间将被关闭。
// 如果 ConnMaxIdleTime <= 0,则连接不会因为空闲而被关闭。
// 默认值是30分钟,-1禁用
ConnMaxIdleTime time.Duration
// ConnMaxLifetime 是一个连接的生存时间,
// 和 ConnMaxIdleTime 不同,ConnMaxLifetime 表示连接最大的存活时间
// 如果 ConnMaxLifetime <= 0,则连接不会有使用时间限制
// 默认值为0,代表连接没有时间限制
ConnMaxLifetime time.Duration
// 如果你的redis服务器需要TLS访问,可以在这里配置TLS证书等信息
// 如果配置了证书信息,go-redis将使用TLS发起连接,
// 如果你自定义了 `Dialer` 方法,你需要自己实现网络连接
TLSConfig *tls.Config
// 限流器的配置,参照 `Limiter` 接口
Limiter Limiter
// 设置启用在副本节点只读查询,默认为false不启用
// 参照:https://redis.io/commands/readonly
readOnly bool
}
*/
实例
package daily
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
"time"
)
var (
Rdb *redis.Client
)
/*
*
go redis
1. 下载依赖: go get github.com/redis/go-redis/v9
2. 参考文档: https://redis.uptrace.dev/zh/guide/go-redis.html
3. 设置临时网络代理:
set http_proxy=http://ip:port
set https_proxy=http://ip:port
4.取消临时网络代理:
set http_proxy=
set https_proxy=
*/
func initRedis() error {
var err error
ctx := context.Background()
// 获取redis连接-1
//dsn := "redis://<user>:<pass>@<host>:<port>/<db>"
//opt, err := redis.ParseURL("redis://redis://localhost:6379/0")
//if err != nil{
// panic(err)
//}else{
// rc := redis.NewClient(opt)
//}
/**
通用客户端
UniversalClient 并不是一个客户端,而是对 Client 、 ClusterClient 、 FailoverClient 客户端的包装。
根据不同的选项,客户端的类型如下:
如果指定了 MasterName 选项,则返回 FailoverClient 哨兵客户端。
如果 Addrs 是 2 个以上的地址,则返回 ClusterClient 集群客户端。
其他情况,返回 Client 单节点客户端。
*/
//// *redis.Client.
//rc := NewUniversalClient(&redis.UniversalOptions{
// Addrs: []string{":6379"},
//})
//
//// *redis.ClusterClient.
//rc := NewUniversalClient(&redis.UniversalOptions{
// Addrs: []string{":6379", ":6380"},
//})
//
//// *redis.FailoverClient.
//rc := NewUniversalClient(&redis.UniversalOptions{
// Addrs: []string{":6379"},
// MasterName: "mymaster",
//})
// 获取redis连接-2
rc := redis.NewClient(&redis.Options{
Addr: "localhost:6379", // 连接地址
Password: "", // 登录密码
DB: 0, // 数据库
})
err = rc.Ping(ctx).Err()
Rdb = rc
return err
}
func RedisOp() {
// 1. 初始化连接
ctx := context.Background()
if err := initRedis(); err != nil {
fmt.Println("连接失败=" + err.Error())
return
} else {
fmt.Println("连接成功")
}
defer Rdb.Close()
// 2. 常规命令
// 2.1 dbsize:统计当前库数据量
if result, err := Rdb.DBSize(ctx).Result(); err != nil {
fmt.Println("命令dbsize执行失败=" + err.Error())
return
} else {
fmt.Println("命令dbsize执行成功=", result)
}
// 2.2 keys *:查找特定库特定key(*:标识匹配所有)
if result, err := Rdb.Keys(ctx, "*").Result(); err != nil {
fmt.Println("命令keys执行失败=" + err.Error())
return
} else {
fmt.Println("命令keys执行成功(切片数据)=", result)
}
// 2.3 exists key:判断特定key是否存在(0:不存在1:存在)
if result, err := Rdb.Exists(ctx, "key").Result(); err != nil {
fmt.Println("命令exists执行失败=" + err.Error())
return
} else {
fmt.Println("命令exists执行成功=", result)
}
// 2.4.1 expire key seconds:设置key有效期
if result, err := Rdb.Expire(ctx, "key", time.Hour*24).Result(); err != nil {
fmt.Println("命令expire执行失败=" + err.Error())
return
} else {
fmt.Println("命令expire执行成功=", result)
}
// 2.4.2 expireat key timestamp:设置key有效期
if result, err := Rdb.ExpireAt(ctx, "key", time.Now().Add(time.Hour*24)).Result(); err != nil {
fmt.Println("命令expireat执行失败=" + err.Error())
return
} else {
fmt.Println("命令expireat执行成功=", result)
}
// 2.5.1 ttl key: 查看key有效期(默认秒|-1:表示永不过期;-2:key不存在)
if result, err := Rdb.TTL(ctx, "key").Result(); err != nil {
fmt.Println("命令ttl执行失败=" + err.Error())
return
} else {
fmt.Println("命令ttl执行成功=", result)
}
// 2.5.2 pttl key:查看key有效期(默认毫秒)
if result, err := Rdb.PTTL(ctx, "key").Result(); err != nil {
fmt.Println("命令pttl执行失败=" + err.Error())
return
} else {
fmt.Println("命令pttl执行成功=", result)
}
// 2.6 type key:查看特定key值类型
if result, err := Rdb.Type(ctx, "key").Result(); err != nil {
fmt.Println("命令type执行失败=" + err.Error())
return
} else {
fmt.Println("命令type执行成功=", result)
}
// 2.7 del key:删除key
if result, err := Rdb.Del(ctx, "key").Result(); err != nil {
fmt.Println("命令del执行失败=" + err.Error())
return
} else {
fmt.Println("命令del执行成功=", result)
}
// 2.8.1 flushdb:清空当前库数据(谨慎执行该指令)
if result, err := Rdb.FlushDB(ctx).Result(); err != nil {
fmt.Println("命令flushdb执行失败=" + err.Error())
return
} else {
fmt.Println("命令flushdb执行成功=", result)
}
// 2.8.2 flushall:清空所有库数据(谨慎执行该指令)
if result, err := Rdb.FlushAll(ctx).Result(); err != nil {
fmt.Println("命令flushall执行失败=" + err.Error())
return
} else {
fmt.Println("命令flushall执行成功=", result)
}
// 3.string(基本数据类型操作)
// 3.1 set
if err := Rdb.Set(ctx, "key", "val", 0).Err(); err != nil {
fmt.Println("string-set-error=" + err.Error())
return
} else {
fmt.Println("string-set(key=val)")
}
// 3.2 get
if result, err := Rdb.Get(ctx, "key").Result(); err == redis.Nil {
fmt.Println("string-key is not exist")
} else if err != nil {
fmt.Println("string-get-error=" + err.Error())
} else {
fmt.Println("string-get(key=key)=" + result)
}
/**
127.0.0.1:6379> EVAL "redis.call('SET', KEYS[1], ARGV[1]);redis.call('EXPIRE', KEYS[1], ARGV[2]); return 1;" 1 userAge 10 60
(integer) 1
127.0.0.1:6379>SCRIPT FLUSH
命令格式:EVAL script numkeys key [key …] arg [arg …]
- script参数是一段 Lua5.1 脚本程序。脚本不必(也不应该[^1])定义为一个 Lua 函数
- numkeys指定后续参数有几个key,即:key [key …]中key的个数。如没有key,则为0
- key [key …] 从 EVAL 的第三个参数开始算起,表示在脚本中所用到的那些 Redis 键(key)。在Lua脚本中通过KEYS[1], KEYS[2]获取。
- arg [arg …] 附加参数。在Lua脚本中通过ARGV[1],ARGV[2]获取。
*/
// 4. 执行lua脚本
// redis-cli -a <password> -h <ip> -p <port> --eval <lua脚本> <key>, <args....>
// redis-cli --eval limitIpVisit.lua limitIp, 10, 3
luaScript := `
redis.call('SET', KEYS[1], ARGV[1]);
redis.call('EXPIRE', KEYS[1], ARGV[2]);
return "success";
`
script := redis.NewScript(luaScript)
if result, err := script.Run(ctx, Rdb, []string{"luaKey"}, []interface{}{1, 3600}).Result(); err != nil {
fmt.Println("lua执行失败=" + err.Error())
return
} else {
fmt.Println("lua执行成功=", result)
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示