Redis 不要只会用 set 和 get 啦,全命令看这篇就够了!

如果你以为只会用 set 和 get 就能自称 Redis 高手,那简直是对 Redis 的能力有点大不敬,哈哈。

Redis 是目前广泛使用的 NoSQL 数据库之一,凭借其强大的数据结构、内存操作性能和丰富的特性,成为许多高性能应用的首选。

对于 Go 语言的开发者,go-redis/redis 提供了一个功能全面且高效的 Redis 客户端库,支持 Redis 的所有操作。

在这篇文章中将会介绍如何使用 go-redis/redis,探索它的所有特性,并提供丰富的示例代码,帮助大家更好地掌握并使用它,好了,下面直接开始。

1. 安装 go-redis

可以使用以下命令安装:

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

2. 基本连接

你可以通过 redis.NewClient 方法创建 Redis 客户端。

package main

import (
 "context"
 "fmt"
 "github.com/go-redis/redis/v8"
)

var ctx = context.Background()

func main() {
 // 创建 Redis 客户端
 rdb := redis.NewClient(&redis.Options{
  Addr:     "localhost:6379", // Redis 地址
  Password: "",               // Redis 密码
  DB:       0,                // 使用默认数据库
 })

 // 测试连接
 pong, err := rdb.Ping(ctx).Result()
 if err != nil {
  fmt.Println("无法连接到 Redis:", err)
 } else {
  fmt.Println("连接成功:", pong)
 }
}

3. 基本 Redis 操作

设置键值对:SET

err := rdb.Set(ctx, "key", "value", 0).Err()
if err != nil {
 fmt.Println("设置键值对失败:", err)
}

获取键值:GET

val, err := rdb.Get(ctx, "key").Result()
if err != nil {
 fmt.Println("获取键值失败:", err)
} else {
 fmt.Println("键值为:", val)
}

删除键:DEL

err := rdb.Del(ctx, "key").Err()
if err != nil {
 fmt.Println("删除键失败:", err)
}

4. 键过期时间

在 Redis 中,可以为键设置过期时间。

你可以使用 Set 方法中的第三个参数来指定键的过期时间,或者使用 Expire 方法单独设置过期时间。

设置键值和过期时间:

// 设置键值并设置过期时间为10秒
err := rdb.Set(ctx, "key", "value", 10*time.Second).Err()

手动设置过期时间:

err := rdb.Expire(ctx, "key", 10*time.Second).Err()

5. Redis 数据结构操作

Redis 支持多种数据结构,如字符串、列表、集合、哈希和有序集合等。

字符串操作:

rdb.Set(ctx, "name", "John", 0)        // 设置字符串值
name, _ := rdb.Get(ctx, "name").Result() // 获取字符串值
fmt.Println("Name:", name)

列表操作:

rdb.RPush(ctx, "list", "item1")         // 向列表右侧推入元素
rdb.LPush(ctx, "list", "item2")         // 向列表左侧推入元素
items, _ := rdb.LRange(ctx, "list", 0, -1).Result() // 获取列表中的所有元素
fmt.Println("List items:", items)

集合操作:

rdb.SAdd(ctx, "set", "member1", "member2")   // 向集合添加元素
members, _ := rdb.SMembers(ctx, "set").Result() // 获取集合中的所有成员
fmt.Println("Set members:", members)

哈希操作:

rdb.HSet(ctx, "hash", "field1", "value1")    // 设置哈希字段
val, _ := rdb.HGet(ctx, "hash", "field1").Result() // 获取哈希字段的值
fmt.Println("Hash field:", val)

有序集合操作:

rdb.ZAdd(ctx, "zset", &redis.Z{Score: 1, Member: "member1"}) // 添加有序集合元素
zrange, _ := rdb.ZRangeWithScores(ctx, "zset", 0, -1).Result() // 获取有序集合元素
fmt.Println("ZSet elements:", zrange)

6. Redis 事务(Transactions)

go-redis 提供了对 Redis 事务的支持。

通过 Watch 和 TxPipelined 你可以实现多操作事务。

err := rdb.Watch(ctx, func(tx *redis.Tx) error {
 // 获取 key 的当前值
 n, err := tx.Get(ctx, "counter").Int()
 if err != nil && err != redis.Nil {
  return err
 }

 // 事务操作:增加 key 的值
 _, err = tx.Pipelined(ctx, func(pipe redis.Pipeliner) error {
  pipe.Set(ctx, "counter", n+1, 0)
  return nil
 })
 return err
}, "counter")

7. 管道(Pipelining)

管道是一种优化 Redis 性能的方式,通过将多个命令一起发送,而不是逐个发送命令,减少网络延迟。

pipe := rdb.Pipeline()
pipe.Set(ctx, "key1", "value1", 0)
pipe.Set(ctx, "key2", "value2", 0)
_, err := pipe.Exec(ctx)

8. 发布与订阅(Pub/Sub)

// 订阅频道
pubsub := rdb.Subscribe(ctx, "channel1")

// 发布消息
rdb.Publish(ctx, "channel1", "hello")

// 接收订阅消息
msg, err := pubsub.ReceiveMessage(ctx)
fmt.Println("Received message:", msg.Payload)

9. 事务管道(Transaction Pipelining)

通过事务管道,你可以将多个事务命令打包在一起,减少交互延迟,同时保持事务的原子性。

pipe := rdb.TxPipeline()
pipe.Set(ctx, "key1", "value1", 0)
pipe.Set(ctx, "key2", "value2", 0)
_, err := pipe.Exec(ctx)

10. Lua 脚本支持

go-redis 允许你直接在 Redis 中执行 Lua 脚本。

script := redis.NewScript(`
 return redis.call('SET', KEYS[1], ARGV[1])
`)

result, err := script.Run(ctx, rdb, []string{"key1"}, "value1").Result()
fmt.Println("Script result:", result)

11. Redis 流(Streams)

Redis 流是 Redis 5.0 引入的一种新的数据结构,适合处理消息流和事件数据。

// 添加流数据
rdb.XAdd(ctx, &redis.XAddArgs{
 Stream: "mystream",
 Values: map[string]interface{}{"name": "John"},
})

// 读取流数据
entries, _ := rdb.XRange(ctx, "mystream", "-", "+").Result()
for _, entry := range entries {
 fmt.Println("Stream entry:", entry)
}

12. 分布式锁

可以使用 SET 命令实现简单的分布式锁,或者使用 Redlock 算法实现更复杂的分布式锁机制。

// 尝试获取锁
ok, err := rdb.SetNX(ctx, "mylock", "locked", 10*time.Second).Result()
if ok {
 fmt.Println("获取锁成功")
} else {
 fmt.Println("锁已存在")
}

13. Redis 集群支持

可以通过 redis.NewClusterClient 来连接到 Redis 集群。

rdb := redis.NewClusterClient(&redis.ClusterOptions{
 Addrs: []string{"localhost:7000", "localhost:7001", "localhost:7002"},
})

pong, err := rdb.Ping(ctx).Result()
fmt.Println(pong, err)

14. Redis 哨兵支持

可以通过 redis.NewFailoverClient 创建哨兵客户端。

rdb := redis.NewFailoverClient(&redis.FailoverOptions{
 MasterName:    "mymaster",
 SentinelAddrs: []string{"localhost:26379", "localhost:26380"},
})

15. 自定义重试机制

提供了自动重试机制,并允许自定义重试次数和策略。

rdb := redis.NewClient(&redis.Options{
 Addr:        "localhost:6379",
 MaxRetries:  5,             // 最大重试 5 次
 MinRetryBackoff: 10 * time.Millisecond, // 最小重试等待时间
 MaxRetryBackoff: 500 * time.Millisecond, // 最大重试等待时间
})

16. 性能监控与指标

可以通过 Redis 的 INFO 命令获取服务器的运行状态和性能指标。

info, err := rdb.Info(ctx, "all").Result()
fmt.Println("Redis Info:", info)

17. Redis 键扫描

通过 SCAN、SSCAN、HSCAN 和 ZSCAN 命令,你可以高效地遍历 Redis 数据,而不会阻塞服务器。

var cursor uint64
var keys []string
for {
 keys, cursor, err = rdb.Scan(ctx, cursor, "*", 10).Result()
 if err != nil {
  break
 }
 for _, key := range keys {
  fmt.Println("Scanned key:", key)
 }
 if cursor == 0 {
  break
 }
}

18. HyperLogLog 操作

Redis 提供了 HyperLogLog 数据结构,用于估算不重复元素的基数。

// 添加元素到 HyperLogLog
err := rdb.PFAdd(ctx, "hll", "item1", "item2", "item3").Err()

// 获取 HyperLogLog 中的基数估算值
count, err := rdb.PFCount(ctx, "hll").Result()
fmt.Println("HyperLogLog 基数:", count)

19. Bitmaps 操作

Redis 支持位图(Bitmaps)操作。

// 设置键的第 7 位为 1
err := rdb.SetBit(ctx, "bitmap_key", 7, 1).Err()

// 获取键的第 7 位的值
bit, err := rdb.GetBit(ctx, "bitmap_key", 7).Result()
fmt.Println("第 7 位的值:", bit)

20. 地理位置(Geo)操作

Redis 支持 GEO 操作,允许你存储、查询地理坐标和进行地理位置相关的操作,例如计算距离、查找附近的点等。

// 添加地理位置
_, err := rdb.GeoAdd(ctx, "locations", &redis.GeoLocation{
 Name:      "Beijing",
 Longitude: 116.4075,
 Latitude:  39.9042,
}).Result()

// 计算两个地点之间的距离
distance, err := rdb.GeoDist(ctx, "locations", "Beijing", "Shanghai", "km").Result()
fmt.Println("北京到上海的距离(公里):", distance)

// 查找某个地点附近的地理位置
nearby, err := rdb.GeoRadius(ctx, "locations", 116.4075, 39.9042, &redis.GeoRadiusQuery{
 Radius:      100,
 Unit:        "km",
 WithCoord:   true,
 WithDist:    true,
 WithHash:    true,
 Count:       10,
 Sort:        "ASC",
}).Result()
for _, loc := range nearby {
 fmt.Printf("地点: %s 距离: %fkm\n", loc.Name, loc.Dist)
}

21. 自定义命令

允许发送自定义的 Redis 命令,适用于 Redis 中某些特殊或不常用的操作。

// 使用 Do 方法发送任意 Redis 命令
result, err := rdb.Do(ctx, "SET", "custom_key", "custom_value").Result()
fmt.Println("自定义命令结果:", result)

22. 自动连接池管理

提供了自动的连接池管理功能。

通过 Options 你可以配置最大连接数、空闲连接数以及连接池的行为。

rdb := redis.NewClient(&redis.Options{
 Addr:        "localhost:6379",
 PoolSize:    20,  // 最大连接数
 MinIdleConns: 5,  // 最小空闲连接数
 IdleTimeout:  5 * time.Minute, // 空闲连接超时时间
})

23. 延迟监控(Latency Monitor)

Redis 提供了延迟监控功能,可以通过 LATENCY LATEST 命令查看最新的延迟情况。

latency, err := rdb.Do(ctx, "LATENCY", "LATEST").Result()
fmt.Println("Redis 延迟监控:", latency)

24. Redis Stream 消费组

Redis 的 Stream 数据结构提供了消费组(Consumer Groups)功能,用于实现类似 Kafka 的消息队列消费模型。

// 创建消费组
err := rdb.XGroupCreateMkStream(ctx, "mystream", "mygroup", "0").Err()

// 消费组读取消息
msgs, err := rdb.XReadGroup(ctx, &redis.XReadGroupArgs{
 Group:    "mygroup",
 Consumer: "consumer1",
 Streams:  []string{"mystream", ">"},
 Count:    10,
 Block:    0,
}).Result()

for _, msg := range msgs[0].Messages {
 fmt.Printf("消息 ID: %s, 值: %v\n", msg.ID, msg.Values)
}

25. 集群模式高级操作

提供了自动路由和高级操作支持。

rdb := redis.NewClusterClient(&redis.ClusterOptions{
 Addrs: []string{"localhost:7000", "localhost:7001", "localhost:7002"},
})

// 在集群模式下设置和获取值
err := rdb.Set(ctx, "key_in_cluster", "value", 0).Err()
val, err := rdb.Get(ctx, "key_in_cluster").Result()
fmt.Println("集群键值:", val)

26. 超时与取消请求

通过 Go 的 context.Context,go-redis 支持请求的超时和取消功能,确保在 Redis 响应过慢或出现异常时,及时取消请求,避免资源浪费。

ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()

_, err := rdb.Get(ctx, "somekey").Result()
if err == context.DeadlineExceeded {
 fmt.Println("请求超时")
} else if err != nil {
 fmt.Println("其他错误:", err)
}

27. 多主模式支持

支持 Redis 的多主模式(multi-master mode),特别适用于高可用架构下的主从复制(Master-Slave Replication)以及 Redis Sentinel 的故障转移(Failover)。

rdb := redis.NewFailoverClient(&redis.FailoverOptions{
 MasterName:    "mymaster",
 SentinelAddrs: []string{"localhost:26379", "localhost:26380"},
})

// 使用哨兵管理主从模式下的连接
val, err := rdb.Get(ctx, "somekey").Result()
fmt.Println("从主服务器获取的值:", val)

28. 自定义 Hook

支持自定义钩子(Hook),可以在请求之前或之后执行自定义逻辑。

常用于日志记录、性能监控或自定义业务逻辑。

type customHook struct{}

func (h customHook) BeforeProcess(ctx context.Context, cmd redis.Cmder) (context.Context, error) {
 fmt.Println("即将执行命令:", cmd)
 return ctx, nil
}

func (h customHook) AfterProcess(ctx context.Context, cmd redis.Cmder) error {
 fmt.Println("命令执行完成:", cmd)
 return nil
}

rdb.AddHook(customHook{})

不得不说,这个 go-redis 真的是太全面了!

无论你是在开发小型项目,还是处理大规模分布式系统,go-redis 都是一个高效、强大且易于使用的解决方案。

在我封装的框架中,Redis 客户端使用的正是 go-redis。

831ba0e3245b24e0afc096fcdd80eda4.jpeg

5062796112ca712208889d8d8b1eec6f.png

3c5c2f8cf2817abf025cf607ec4b9df0.jpeg

可点击下方👇关注公众号

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值