likes
comments
collection
share

Go中redis部署与使用

作者站长头像
站长
· 阅读数 21

前言

本文主要是针对go-redis框架从安装到使用入门, 在实际使用中一定要多参考官方API。

官方API地址:pkg.go.dev/github.com/…

Redis环境部署

在docker中运行如下命令:

docker run --name redis -p 6379:6379 -v your_path/Data/redis/data:/data -d --restart=always redis:latest redis-server --appendonly yes --requirepass "your_password"

执行完后将会得到一个docker容器。

安装go-redis库

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

redis连接方式

  • 普通连接模式
//1. go-redis库使用redis.NewClient函数连接redis服务器
rdb := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379",
        Password: "", // 密码
        DB:       0,  // 数据库
        PoolSize: 20, // 连接池大小
})

//2. redis.ParseURL 函数从表示数据源的字符串中解析得到 Redis 服务器的配置信息。
opt, err := redis.ParseURL("redis://<user>:<pass>@localhost:6379/<db>")
if err != nil {panic(err)
}

rdb := redis.NewClient(opt)
  • TLS连接模式

如果使用的是 TLS 连接方式,则需要使用 tls.Config 配置。

rdb := redis.NewClient(&redis.Options{
    TLSConfig: &tls.Config{
      MinVersion: tls.VersionTLS12,
      // Certificates: []tls.Certificate{cert},
      // ServerName: "your.domain.com",
    },
})
  • Redis Sentinel模式

Sentinel是Redis在主从复制基础上构建的一套高可用解决方案。 不断监听下游服务是不是可用,在主从之间切换模式。

使用下面的命令连接到由 Redis Sentinel 管理的 Redis 服务器。

rdb := redis.NewFailoverClient(&redis.FailoverOptions{
    MasterName:    "master-name",
    SentinelAddrs: []string{":9126", ":9127", ":9128"},
})

  • Redis Cluster模式

集群模式是对redis进行分片冗余存储模式,进而保证服务可用性。

使用下面的命令连接到 Redis Cluster,go-redis 支持按延迟或随机路由命令。

rdb := redis.NewClusterClient(&redis.ClusterOptions{
    Addrs: []string{":7000", ":7001", ":7002", ":7003", ":7004", ":7005"},// 若要根据延迟或随机路由命令,请启用以下命令之一// RouteByLatency: true,// RouteRandomly: true,
})

基本使用

基础使用

package main

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

// doCommand go-redis基本使用示例
func doCommand(rdb *redis.Client) {
   ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
   defer cancel()
   // 执行命令获取结果
   val, err := rdb.Get(ctx, "key").Result()
   fmt.Println(val, err)

   // 先获取到命令对象
   cmder := rdb.Get(ctx, "key")
   fmt.Println(cmder.Val()) // 获取值
   fmt.Println(cmder.Err()) // 获取错误

   // 直接执行命令获取错误
   err = rdb.Set(ctx, "key", 10, time.Hour).Err()

   // 直接执行命令获取值
   value := rdb.Get(ctx, "key").Val()
   fmt.Println(value)
}

func main() {
   fmt.Printf("项目测试")
   rdb := redis.NewClient(&redis.Options{
      Addr:     "localhost:6379",
      Password: "", // 密码
      DB:       0,  // 数据库
      PoolSize: 20, // 连接池大小
   })
   doCommand(rdb)
}

需要格外注意的是 :redis 库的引入加上了,版本号v8. 这样就可以使用带有contextapi命令。在v6版本中是不带ctx的。使用时会提示错。

Go中redis部署与使用

执行任意命令

go-redis 还提供了一个执行任意命令或自定义命令的 Do 方法,特别是一些 go-redis 库暂时不支持的命令都可以使用该方法执行。具体使用方法如下。

// 直接执行命令获取错误
err := rdb.Do(ctx, "set", "key", 10, "EX", 3600).Err()
// 执行命令获取结果
val, err := rdb.Do(ctx, "get", "key").Result()

redis.Nil

go-redis 库提供了一个 redis.Nil 错误来表示 Key 不存在的错误。

因此在使用 go-redis 时需要注意对返回错误的判断。在某些场景下我们应该区别处理 redis.Nil 和其他不为 nil 的错误。

// getValueFromRedis redis.Nil判断
func getValueFromRedis(key, defaultValue string) (string, error) {
        ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
        defer cancel()

        val, err := rdb.Get(ctx, key).Result()
        if err != nil {// 如果返回的错误是key不存在
            if errors.Is(err, redis.Nil) {
                return defaultValue, nil
            }
            // 出其他错了
            return "", err
        }
        return val, nil
}

其他场景

  • Zset: 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。

  • Key: 扫描或遍历所有key。 你可以使用KEYS prefix:\* 命令按前缀获取所有 key。 如果在生产环境中尽量不要这么使用,因为他会造成数据库的阻塞。 scan 命令是一个基于游标的迭代器。 这意味着命令每次被调用都需要使用上一次这个调用返回的游标作为该次调用的游标参数,以此来延续之前的迭代过程。

vals, err := rdb.Keys(ctx, "prefix*").Result()
  • pipline

  • 事务

  • 发布订阅消息

// 发布消息
err := rdb.Publish(ctx, "mychannel1", "payload").Err()
if err != nil {
      panic(err)
}

// 订阅消息
// There is no error because go-redis automatically reconnects on error.
pubsub := rdb.Subscribe(ctx, "mychannel1")
// Close the subscription when we are done.
defer pubsub.Close()


//接收消息
for {
    msg, err := pubsub.ReceiveMessage(ctx)
    if err != nil {
            panic(err)
    }

    fmt.Println(msg.Channel, msg.Payload)
}

//发布消息
ch := pubsub.Channel()
for msg := range ch {
    fmt.Println(msg.Channel, msg.Payload)
}

参考链接:

转载自:https://juejin.cn/post/7282692430116438035
评论
请登录