Redis(远程字典服务器)是一种高性能的内存键值型数据库。它可以作为多种应用程序的缓存、数据库、消息代理和排行榜等。而GoRedis是Golang实现的Redis客户端,增加了不少方便易用的特性。本文将从多个方面详细阐述GoRedis的使用。
一、连接Redis数据库
GoRedis的最基本用法是连接Redis数据库。连接可以使用以下两种方式:
import "github.com/go-redis/redis/v8"
func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
pong, err := rdb.Ping(ctx).Result()
fmt.Println(pong, err)
}
或者使用连接池:
func main() {
import (
"context"
"fmt"
"time"
"github.com/go-redis/redis/v8"
)
func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
DB: 0,
})
defer rdb.Close()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
pong, err := rdb.Ping(ctx).Result()
fmt.Println(pong, err)
poolSize := 10
maxPoolSize := 30
timeout := 2 * time.Second
rdbPool := &redis.Pool{
MaxIdle: poolSize,
MaxActive: maxPoolSize,
IdleTimeout: timeout,
Dial: func() (redis.Conn, error) {
conn, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
return nil, err
}
return conn, nil
},
}
defer rdbPool.Close()
conn := rdbPool.Get()
defer conn.Close()
pong2, err := redis.String(conn.Do("PING"))
fmt.Println(pong2, err)
}
二、设置和获取过期时间
Redis的值可以设置过期时间,通过GoRedis也能轻易应用。使用TTL方法获取一个键的剩余过期时间,EXPIRE和EXPIREAT方法设置, DEL方法删除这个键值即可。
import "github.com/go-redis/redis/v8"
func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
err := rdb.Set(ctx, "key", "value", time.Hour).Err()
if err != nil {
panic(err)
}
ttl, err := rdb.TTL(ctx, "key").Result()
if err != nil {
panic(err)
}
fmt.Println(ttl)
err = rdb.Expire(ctx, "key", time.Minute).Err()
if err != nil {
panic(err)
}
err = rdb.ExpireAt(ctx, "key", time.Now().Add(24*time.Hour)).Err()
if err != nil {
panic(err)
}
n, err := rdb.Del(ctx, "key").Result()
if err != nil {
panic(err)
}
fmt.Println(n)
}
三、GoRedis和Redis的数据类型匹配
Redis有多种数据类型,GoRedis也提供了对应的Go语言数据结构相应的API,相对应的数据类型包括:
字符串(Strings)
操作字符串可以使用GET方法获取整个字符串,SET方法设置。也可以使用SETEX方法设置带有过期时间的键值对,使用APPEND方法增加字符串长度。
哈希(Hashes)
对于哈希,可使用HSET方法设置,HMSET方法设置多组键值对。添加、删除和获取同理,并且通过HGETALL方法可以获得哈希表中所有的键值对。
列表(Lists)
对于列表,使用LPUSH方法可以在列表前面添加元素,使用RPUSH方法可以在列表尾部添加元素。
import "github.com/go-redis/redis/v8"
func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
err := rdb.LPush(ctx, "key", "value", "value2").Err()
if err != nil {
panic(err)
}
err = rdb.RPush(ctx, "key", "value", "value2").Err()
if err != nil {
panic(err)
}
val, err := rdb.LPop(ctx, "key").Result()
if err != nil {
panic(err)
}
fmt.Println(val)
vals, err := rdb.LRange(ctx, "key", 0, -1).Result()
if err != nil {
panic(err)
}
for _, val := range vals {
fmt.Println(val)
}
}
集合(Sets)
对于集合,SET和SADD方法可以添加元素,SPOP方法可以删除并返回随机一个元素。
有序集合(Sorted Sets)
对于有序集合,ZADD方法可以添加有序元素的成员和score值,ZRANGE和ZREVRANGE获取对应元素的区间。
import "github.com/go-redis/redis/v8"
func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
err := rdb.ZAdd(ctx, "key", &redis.Z{Score: 1, Member: "value1"}, &redis.Z{Score: 2, Member: "value2"}).Err()
if err != nil {
panic(err)
}
vals, err := rdb.ZRange(ctx, "key", 0, -1).Result()
if err != nil {
panic(err)
}
fmt.Println(vals)
vals, err = rdb.ZRevRange(ctx, "key", 0, -1).Result()
if err != nil {
panic(err)
}
fmt.Println(vals)
}
四、GoRedis的一些高级特性
事务(Transactions)
在GoRedis中,MULTI,EXEC,WATCH方法可以实现事务操作。首先使用WATCH方法监视某个值,当这个值发生变化时,MULTI方法之间的代码块才会执行,而EXEC方法会执行MULTI方法块内的所有操作。
import "github.com/go-redis/redis/v8"
func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
err := rdb.Watch(ctx, func(tx *redis.Tx) error {
v, err := tx.Get(ctx, "key").Result()
if err != nil {
return err
}
new := v + "bar"
_, err = tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error {
pipe.Set(ctx, "key", new, 0)
return nil
})
if err != nil {
return err
}
return nil
}, "key")
if err != nil {
panic(err)
}
}
发布和订阅(Pub/Sub)
GoRedis也支持Redis中的发布和订阅功能。通过Subscrip和Subscribe方法,连接到频道并接收消息。使用Publish方法发布数据。
import (
"fmt"
"github.com/go-redis/redis/v8"
"time"
)
func main() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
pubsub := rdb.Subscribe(ctx, "channel1")
_, err := pubsub.Receive(ctx)
if err != nil {
panic(err)
}
ch := pubsub.Channel()
go func() {
for msg := range ch {
fmt.Println(msg.Channel, msg.Payload)
}
}()
err = rdb.Publish(ctx, "channel1", "hello").Err()
if err != nil {
panic(err)
}
time.Sleep(time.Second)
_ = pubsub.Close()
_ = rdb.Close()
}
管道(Pipeline)
GoRedis的另一个高级功能是管道。使用该功能可将多个Redis操作组合成一组命令,可以显著减少网络延迟,并在秒级别执行这些操作。
import "github.com/go-redis/redis/v8"
func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
pipe := rdb.Pipeline()
incr := pipe.Incr(ctx, "pipeline_counter")
pipe.Expire(ctx, "pipeline_counter", time.Hour)
_, err := pipe.Exec(ctx)
if err != nil {
panic(err)
}
fmt.Println(incr.Val())
}
结论
本文从连接Redis数据库,设置和获取过期时间,GoRedis和Redis的数据类型匹配,GoRedis的一些高级特性等方面详细阐述了GoRedis的使用方法。GoRedis不仅支持Redis的基本操作,还提供了一些高级特性,如事务、发布和订阅、管道等。