Golang操作Redis

Redis是一种流行的内存键值数据库,被广泛用于构建高性能的缓存和消息队列应用。本文将介绍如何通过go-redis访问redis。

1. 安装依赖

go get github.com/go-redis/redis

golang 如何连接 redis

client := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379", // redis地址
        Password: "",               // 密码
        DB:       0,                // 使用默认数据库
		ReadTimeout: 3,             // socket读取超时时间, 默认 3s
        WriteTimeout: 10,           // socket写超时时间
        MinRetryBackoff: 10 * time.Second,  // 最大重试时间间隔, 默认是 512ms; -1 表示关闭
})

提示:go-redis包自带了连接池,会自动维护redis连接,因此创建一次client即可,不要查询一次redis就关闭client。

Options参数详解

type Options struct {
    // 网络类型 tcp 或者 unix.
    // 默认是 tcp.
    Network string
    // redis地址,格式 host:port
    Addr string
	
    // 新建一个redis连接的时候,会回调这个函数
    OnConnect func(*Conn) error
    
    // redis密码,redis server没有设置可以为空。
    Password string
    
    // redis数据库,序号从0开始,默认是0,可以不用设置
    DB int
    
    // redis操作失败最大重试次数,默认不重试。
    MaxRetries int
    
    // 最小重试时间间隔. 默认是 8ms ; -1 表示关闭.
    MinRetryBackoff time.Duration    
    // 最大重试时间间隔. 默认是 512ms; -1 表示关闭.
    MaxRetryBackoff time.Duration
    
    // redis连接超时时间. 默认是 5 秒.
    DialTimeout time.Duration
    
    // socket读取超时时间. 默认 3 秒.
    ReadTimeout time.Duration    
    // socket写超时时间
    WriteTimeout time.Duration
    
    // redis连接池的最大连接数. 默认连接池大小等于 cpu个数 * 10
    PoolSize int
    
    // redis连接池最小空闲连接数.
    MinIdleConns int
    // redis连接最大的存活时间,默认不会关闭过时的连接.
    MaxConnAge time.Duration
    
    // 当你从redis连接池获取一个连接之后,连接池最多等待这个拿出去的连接多长时间。 默认是等待 ReadTimeout + 1 秒.
    PoolTimeout time.Duration
    // redis连接池多久会关闭一个空闲连接. 默认是 5 分钟. -1 则表示关闭这个配置项
    IdleTimeout time.Duration
    // 多长时间检测一下,空闲连接. 默认是 1 分钟. -1 表示关闭空闲连接检测
    IdleCheckFrequency time.Duration
    
    // 只读设置,如果设置为true, redis只能查询缓存不能更新。
    readOnly bool
}

2. 基本的 set、get 操作

package main

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

/**
    安装依赖:
	    go get github.com/go-redis/redis
*/

// 创建redis客户端
func newClient() *redis.Client {
    client := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379", // redis地址
        Password: "",               // 密码
        DB:       0,                // 使用默认数据库
		ReadTimeout: 3,             // socket读取超时时间, 默认 3s
        WriteTimeout: 10,           // socket写超时时间
        MinRetryBackoff: 10 * time.Second,  // 最大重试时间间隔, 默认是 512ms; -1 表示关闭
    })
    return client
}

func main() {
    // 创建redis客户端
    client := newClient()
    defer client.Close() 

    // 设置 key, 第三个参数代表key的过期时间, 0代表不会过期
    err := client.Set("name", "john", 0).Err()
    if err != nil {
        panic(err)
    }
	// 设置过期时间 key
	// err := client.Set("key", "value", 100* time.Second ).Err()

    // 获取key
    val, err := client.Get("name").Result()
    if err != nil {
        panic(err)
    }
    fmt.Println("name", val)
	
	val2, err := rdb.Get("age").Result()
    // redis.Nil 表示这个key 在Redis中不存在
	if err == redis.Nil {
		fmt.Println("key2 does not exists")
	} else if err != nil {
		panic(err)
	} else {
		fmt.Println("key2", val2)
	}
}

redis.NewClient 创建了一个Redis客户端。然后使用 set方法设置了一个key-value,之后使用get方法获取它的值。 Get的结果可能是 redis.Nil 表示这个key 在Redis中不存在。

3. hash 操作

  // Set hash field
  err := client.HSet( "myhash", "field1", "value1").Err()
  if err != nil {
    panic(err)
  }

  // Fetch hash field
  val, err := client.HGet("myhash", "field1").Result()
  if err != nil {
    panic(err)
  }
  fmt.Println("myhash field1:", val)

  // Delete hash field
  err = client.HDel( "myhash", "field1").Err()
  if err != nil {
    panic(err)
  }

  // Fetch all hash fields
  vals, err := client.HGetAll( "myhash").Result()
  if err != nil {
    panic(err)
  }
  fmt.Println("myhash:", vals)

4. pubsub发布订阅

package main

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

func subscriber(client *redis.Client) {
    pubsub := client.Subscribe("mychannel")
    defer pubsub.Close()

    // 处理订阅接收到的消息
    for {
        msg, err := pubsub.ReceiveMessage()
        if err != nil {
            return
        }
        fmt.Println(msg.Channel, msg.Payload)
    }
}

func publisher(client *redis.Client) {
    for {
        // 发布消息到频道
        err := client.Publish("mychannel", "hello").Err()
        if err != nil {
            panic(err)
        }
    }
}

func main() {
    client := redis.NewClient(&redis.Options{
        Addr: "localhost:6379",
    })

    go subscriber(client)
    go publisher(client)

    <-make(chan struct{})
}

使用 go-redis 可以方便地实现发布订阅模型:

  • 通过 client.Subscribe 订阅了一个频道,然后在循环里接收消息。
  • 另开一个 goroutine发布消息。

5. 消息队列示例

package main

import (
    "fmt"
    "math/rand"
    "time"
    "github.com/go-redis/redis"
)

var client *redis.Client 

// 初始化连接
func initClient() {
    client = redis.NewClient(&redis.Options{
        Addr:     "localhost:6379",
        Password: "", 
        DB:       0, 
    })
}

// 生产者 - 发布消息
func producer() {
    for {
        message := rand.Intn(1000)
        err := client.LPush("queue", message).Err()
        if err != nil {
            panic(err)
        }
        fmt.Println("pushed", message)
        time.Sleep(1 * time.Second)
    }
}

// 消费者 - 处理消息
func consumer(id int) {
    for {
        message, err := client.BRPop(0, "queue").Result()
        if err != nil {
            panic(err)
        }
        fmt.Printf("consumer%d popped %s \n", id, message[1])
        time.Sleep(500 * time.Millisecond)
    }
}

func main() {
    // 初始化
    initClient()
    // 生产者goroutine
    go producer()
    // 3个消费者goroutine
    for i := 0; i < 3; i++ {
        go consumer(i)
    }
    // 阻塞主goroutine
    <-make(chan struct{}) 
}

使用BRPop实现阻塞式出队,LPush入队,可以构建基于Redis的消息队列。 多个消费者可以共享队列实现负载均衡。

更加详细的redis操作,见下一篇讲解 go-redis 的各种 API 使用。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值