go-redis 是 Go 编程语言的官方 Redis 客户端库。它提供了与 Redis 服务器交互的简单接口。
在 go-redis
中,我们计划支持 Redis 的最新三个版本。目前,这意味着我们支持:
虽然 go.mod
声明它至少需要 go 1.18
版本,我们的 CI 配置为针对 Redis 的所有三个版本和最新的两个 Go 版本(1.23、
1.24) 运行测试。我们观察到,某些模块相关的测试可能无法通过 Redis Stack 7.2 的测试,并且某些命令在 Redis CE 8.0 中有所更改。
如果您遇到任何问题,请参考文档和测试。我们计划在下一个版本中将 go.mod
中的 go 版本更新为 go 1.24
。
此客户端也适用于Kvrocks,一个分布式键值 NoSQL 数据库,使用 RocksDB 作为存储引擎,并兼容 Redis 协议。
go-redis 支持最近两个 Go 版本,并且需要一个支持 模块 的 Go 版本。因此,请确保初始化 Go 模块:
go mod init github.com/my/repo
Then install go-redis/v9:
go get github.com/redis/go-redis/v9
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)
var ctx = context.Background()
func ExampleClient() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
})
err := rdb.Set(ctx, "key", "value", 0).Err()
if err != nil {
panic(err)
}
val, err := rdb.Get(ctx, "key").Result()
if err != nil {
panic(err)
}
fmt.Println("key", val)
val2, err := rdb.Get(ctx, "key2").Result()
if err == redis.Nil {
fmt.Println("key2 does not exist")
} else if err != nil {
panic(err)
} else {
fmt.Println("key2", val2)
}
// Output: key value
// key2 does not exist
}
Redis 客户端支持多种提供身份验证凭据的方式,并具有明确的优先级顺序。以下是可用的选项:
流式凭据提供程序允许在连接生命周期内动态更新凭据。这对于托管身份服务和基于令牌的身份验证尤其有用。
type StreamingCredentialsProvider interface {
Subscribe(listener CredentialsListener) (Credentials, UnsubscribeFunc, error)
}
type CredentialsListener interface {
OnNext(credentials Credentials) // Called when credentials are updated
OnError(err error) // Called when an error occurs
}
type Credentials interface {
BasicAuth() (username string, password string)
RawCredentials() string
}
Example usage:
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
StreamingCredentialsProvider: &MyCredentialsProvider{},
})
**注意:**流式凭据提供程序可与 go-redis-entraid 一起使用,以启用 Entra ID(以前称为 Azure AD)身份验证。这允许与 Azure 的托管身份服务和基于令牌的身份验证无缝集成。
Example with Entra ID:
import (
"github.com/redis/go-redis/v9"
"github.com/redis/go-redis-entraid"
)
// Create an Entra ID credentials provider
provider := entraid.NewDefaultAzureIdentityProvider()
// Configure Redis client with Entra ID authentication
rdb := redis.NewClient(&redis.Options{
Addr: "your-redis-server.redis.cache.windows.net:6380",
StreamingCredentialsProvider: provider,
TLSConfig: &tls.Config{
MinVersion: tls.VersionTLS12,
},
})
基于上下文的提供程序允许在每次操作时使用上下文确定凭证。
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
CredentialsProviderContext: func(ctx context.Context) (string, string, error) {
// 返回用户名、密码和任何错误
return "user", "pass", nil
},
})
一个基于函数的简单提供程序,返回静态凭证。
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
CredentialsProvider: func() (string, string) {
// 返回用户名和密码
return "user", "pass"
},
})
提供凭据的最基本方法是通过选项中的 Username
和 Password
字段。
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Username: "user",
Password: "pass",
})
客户端将按以下优先级顺序使用凭证:
如果以上均未设置,客户端将尝试在未进行身份验证的情况下进行连接。
客户端支持 RESP2 和 RESP3 协议。您可以在选项中指定协议版本:
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
Protocol: 3, // specify 2 for RESP 2 or 3 for RESP 3
})
go-redis 还支持通过 redis uri 规范 进行连接。
以下示例演示了如何遵循此规范,使用字符串轻松配置连接。
import (
"github.com/redis/go-redis/v9"
)
func ExampleClient() *redis.Client {
url := "redis://user:password@localhost:6379/0?protocol=3"
opts, err := redis.ParseURL(url)
if err != nil {
panic(err)
}
return redis.NewClient(opts)
}
import (
"github.com/redis/go-redis/v9"
"github.com/redis/go-redis/extra/redisotel/v9"
"errors"
)
func main() {
...
rdb := redis.NewClient(&redis.Options{...})
if err := errors.Join(redisotel.InstrumentTracing(rdb), redisotel.InstrumentMetrics(rdb)); err != nil {
log.Fatal(err)
}
go-redis 默认使用 0.5MiB 的读写缓冲区以获得最佳性能。对于高吞吐量应用程序或大型管道,您可以自定义缓冲区大小:
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
ReadBufferSize: 1024 * 1024, // 1MiB 读取缓冲区
WriteBufferSize: 1024 * 1024, // 1MiB 写入缓冲区
})
go-redis 支持扩展客户端标识阶段,允许项目发送自定义客户端标识。
默认情况下,go-redis 会在连接过程中自动发送客户端库名称和版本。此功能在 redis-server 7.2 及更高版本中可用。因此,该命令是“触发后不管”的,这意味着如果 Redis 服务器不支持此功能,它应该会静默失败。
当不需要连接身份验证或需要明确禁用连接身份验证时,可以使用“DisableIdentity”配置选项。
最初存在拼写错误,该选项被命名为“DisableIndentity”而不是“DisableIdentity”。拼写错误的选项已被标记为“已弃用”,并将在本库的 V10 版本中移除。
虽然目前这两个选项都可以使用,但正确的选项是“DisableIdentity”。已弃用的选项将在本库的 V10 版本中移除,因此请使用正确的选项名称以避免出现任何问题。
要禁用验证,请在 Redis 客户端选项中将 DisableIdentity
选项设置为 true
:
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
DisableIdentity: true, // 连接时禁用 set-info
})
在使用 RESP3 将 Redis 与应用程序功能集成时,需要注意的是,某些响应结构尚未最终确定。对于搜索和查询结果等更复杂的结构尤其如此。我们建议在使用搜索和查询功能时使用 RESP2,但我们计划在未来的版本中稳定基于 RESP3 的 API。您可以在即将发布的发行说明中找到更多指导。
要启用不稳定的 RESP3,请在客户端配置中设置以下选项:
redis.NewClient(&redis.Options{
UnstableResp3: true,
})
**注意:**启用 UnstableResp3 模式后,需要使用 RawResult() 和 RawVal() 来检索原始数据。
由于原始响应是不稳定搜索命令的唯一选项,因此 Val() 和 Result() 调用不会对它们产生任何影响:
res1, err := client.FTSearchWithArgs(ctx, "txt", "foo bar", &redis.FTSearchOptions{}).RawResult()
val1 := client.FTSearchWithArgs(ctx, "txt", "foo bar", &redis.FTSearchOptions{}).RawVal()
在 Redis-Search 模块中,默认方言为 2。如果需要,您可以在查询中使用相应的配置明确指定其他方言。
重要提示:请注意,查询方言可能会影响返回的结果。如果需要,您可以通过在要执行的命令的参数中传递所需的方言来恢复到其他方言版本。
例如:
res2, err := rdb.FTSearchWithArgs(ctx,
"idx:bicycle",
"@pickup_zone:[CONTAINS $bike]",
&redis.FTSearchOptions{
Params: map[string]interface{}{
"bike": "POINT(-0.1278 51.5074)",
},
DialectVersion: 3,
},
).Result()
您可以在查询方言文档中找到更多详细信息。
在 v9.12 之前,缓冲区大小为 Go 默认的 4096 字节。从 v9.12 开始,
go-redis 默认使用 256KiB 的读写缓冲区以获得最佳性能。
对于高吞吐量应用程序或大型管道,您可以自定义缓冲区大小:
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
ReadBufferSize: 1024 * 1024, // 1MiB 读取缓冲区
WriteBufferSize: 1024 * 1024, // 1MiB 写入缓冲区
})
重要提示:如果您在使用默认缓冲区大小时遇到任何问题,请尝试将其设置为 Go 默认的 4096 字节。
我们欢迎您为 go-redis 库做出贡献!如果您有错误修复、功能请求或改进,请在 GitHub 上提交问题或拉取请求。
感谢您帮助我们改进 go-redis,使其更适合所有人。
如果您有兴趣为 go-redis 库做出贡献,请查看我们的贡献指南 (CONTRIBUTING.md),了解更多关于如何开始的信息。
一些特殊情况:
// SET key value EX 10 NX
set, err := rdb.SetNX(ctx, "key", "value", 10*time.Second).Result()
// SET key value keepttl NX
set, err := rdb.SetNX(ctx, "key", "value", redis.KeepTTL).Result()
// SORT list LIMIT 0 2 ASC
vals, err := rdb.Sort(ctx, "list", &redis.Sort{Offset: 0, Count: 2, Order: "ASC"}).Result()
// ZRANGEBYSCORE zset -inf +inf WITHSCORES LIMIT 0 2
vals, err := rdb.ZRangeByScoreWithScores(ctx, "zset", &redis.ZRangeBy{
Min: "-inf",
Max: "+inf",
Offset: 0,
Count: 2,
}).Result()
// ZINTERSTORE out 2 zset1 zset2 WEIGHTS 2 3 AGGREGATE SUM
vals, err := rdb.ZInterStore(ctx, "out", &redis.ZStore{
Keys: []string{"zset1", "zset2"},
Weights: []int64{2, 3}
}).Result()
// EVAL "return {KEYS[1],ARGV[1]}" 1 "key" "hello"
vals, err := rdb.Eval(ctx, "return {KEYS[1],ARGV[1]}", []string{"key"}, "hello").Result()
// custom command
res, err := rdb.Do(ctx, "set", "key", "value").Result()
go-redis 将启动 redis 服务器并运行测试用例。
redis-server bin 文件和 redis 配置文件的路径在 main_test.go
文件中定义:
var (
redisServerBin, _ = filepath.Abs(filepath.Join("testdata", "redis", "src", "redis-server"))
redisServerConf, _ = filepath.Abs(filepath.Join("testdata", "redis", "redis.conf"))
)
对于本地测试,您可以更改变量以引用本地文件,或者创建指向 redis-server 相应文件夹的软链接,并将配置文件复制到 testdata/redis/
目录:
ln -s /usr/bin/redis-server ./go-redis/testdata/redis/src
cp ./go-redis/testdata/redis.conf ./go-redis/testdata/redis/
最后,运行:
go test
另一种选择是使用已经运行的 redis 运行你的特定测试。以下示例测试了运行在 9999 端口的 redis:
REDIS_PORT=9999 go test <你的选项>