Go中redis部署与使用

前言

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

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

Redis环境部署

在docker中运行如下命令:

Go 复制代码
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库

Bash 复制代码
go get github.com/go-redis/redis/v8

redis连接方式

  • 普通连接模式
Go 复制代码
//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 配置。

Go 复制代码
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 服务器。

Go 复制代码
rdb := redis.NewFailoverClient(&redis.FailoverOptions{
    MasterName:    "master-name",
    SentinelAddrs: []string{":9126", ":9127", ":9128"},
})
  • Redis Cluster模式

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

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

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

基本使用

基础使用

Go 复制代码
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 还提供了一个执行任意命令或自定义命令的 Do 方法,特别是一些 go-redis 库暂时不支持的命令都可以使用该方法执行。具体使用方法如下。

Go 复制代码
// 直接执行命令获取错误
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 的错误。

Go 复制代码
// 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 命令是一个基于游标的迭代器。 这意味着命令每次被调用都需要使用上一次这个调用返回的游标作为该次调用的游标参数,以此来延续之前的迭代过程。

Go 复制代码
vals, err := rdb.Keys(ctx, "prefix*").Result()
  • pipline

  • 事务

  • 发布订阅消息

Go 复制代码
// 发布消息
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)
}

参考链接:

相关推荐
云和数据.ChenGuang7 小时前
Django 应用安装脚本 – 如何将应用添加到 INSTALLED_APPS 设置中 原创
数据库·django·sqlite
我是前端小学生14 小时前
Go语言中的方法和函数
go
探索云原生19 小时前
在 K8S 中创建 Pod 是如何使用到 GPU 的: nvidia device plugin 源码分析
ai·云原生·kubernetes·go·gpu
LuiChun1 天前
Django 模板分割及多语言支持案例【需求文档】-->【实现方案】
数据库·django·sqlite
凡人的AI工具箱1 天前
每天40分玩转Django:Django管理界面
开发语言·数据库·后端·python·django
中科院提名者1 天前
Django连接mysql数据库报错ModuleNotFoundError: No module named ‘MySQLdb‘
数据库·mysql·django
碧水澜庭1 天前
django中cookie与session的使用
python·django
鬼义II虎神1 天前
将Minio设置为Django的默认Storage(django-storages)
python·django·minio·django-storages
自在的LEE1 天前
当 Go 遇上 Windows:15.625ms 的时间更新困局
后端·kubernetes·go
大霸王龙1 天前
在 Django 中使用 SMTP 发送邮件是一个常见的需求
数据库·django·sqlite