go-redis开发手册:Go语言玩转Redis的正确姿势

2023-07-1308:07:26后端程序开发Comments1,238 views字数 3956阅读模式

Redis是一种流行的内存键值数据库,被广泛用于构建高性能的缓存和消息队列应用。本文将介绍如何通过go-redis访问redis。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/51431.html

go-redis简介

go-redis是一个Go语言中非常流行的Redis客户端库。相比于其他Go语言Redis客户端,它具有以下优点:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/51431.html

  1. API友好,命令名称和参数与Redis原生命令一致,使用简单方便。
  2. 支持完整的Redis命令集,覆盖了字符串、哈希、列表、集合、有序集合、HyperLogLog等数据结构。
  3. 支持连接池,可以有效控制连接数,避免频繁创建连接。
  4. 支持Pipeline和事务,可以打包多个命令减少网络开销。
  5. 支持发布订阅Pub/Sub和键空间通知等功能。
  6. 支持哨兵和集群模式,提供高可用能力。
  7. 代码维护活跃,持续有新功能加入。
  8. 在Github上拥有1.5万+星,是最流行的Go Redis客户端。

总之,go-redis是一个功能完备、易用性高的Redis客户端库,它覆盖了Redis的绝大部分功能,是Go语言连接Redis的首选方案。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/51431.html

go-redis使用demo

package main
import (    "fmt"
    "github.com/go-redis/redis")
// 创建redis客户端func newClient() *redis.Client {    client := redis.NewClient(&redis.Options{        Addr:     "localhost:6379", // redis地址        Password: "",               // 密码        DB:       0,                // 使用默认数据库    })    return client}
func main() {
    // 创建客户端    client := newClient()    defer client.Close() 
    // 设置key    err := client.Set("name", "john", 0).Err()    if err != nil {        panic(err)    }
    // 获取key    val, err := client.Get("name").Result()    if err != nil {        panic(err)    }    fmt.Println("name", val)
}

如代码所示,go-redis提供了非常简洁的API来连接Redis服务器,执行命令文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/51431.html

go-redis 常用功能

发布订阅

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{})}
  • 通过client.Subscribe订阅了一个频道,然后在循环里接收消息。
  • 另开一个goroutine发布消息。使用go-redis可以方便地实现发布订阅模型。

消息队列

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的消息队列。
  • 多个消费者可以共享队列实现负载均衡

pipeline访问

Redis Pipeline实现了一种批量发送请求和响应的模式,它允许客户端在单次网络交互中缓冲并发送多个命令,然后再次单次接收所有响应。这种方式极大地减少了客户端和服务器之间的网络往返次数,优化了网络传输开销,显著提升Redis的总体吞吐量和命令处理性能。测试结果表明,Pipeline模式可以使Redis命令处理的TPS吞吐量提升数倍。同时它也减轻了客户端等待响应的时间,有效隐藏了网络通信时延。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/51431.html

此外,Pipeline模式下可轻松传输更大的数据包,避免小包命令多次网络传输的资源消耗。它还可以减少客户端和服务器端的CPU和内存占用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/51431.html

总之,Redis Pipeline通过优化网络传输、批量命令执行等手段,极大地提升了Redis的性能,是非常重要的客户端访问优化方式。它尤其适合用于高负载、低延迟的Redis访问场景。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/51431.html

func pipelineDemo(client *redis.Client) {    // 创建pipeline    pipe := client.Pipeline()
    // 添加多个命令到pipeline    setCmd := pipe.Set("key1", "value1", 0)    getCmd := pipe.Get("key1")    incrCmd := pipe.Incr("counter")    pipe.Expire("key1", time.Hour)
    // 执行pipeline    _, err := pipe.Exec()    if err != nil {        panic(err)    }
    fmt.Println("setCmd:", setCmd.Val())    fmt.Println("getCmd:", getCmd.Val())    fmt.Println("incrCmd:", incrCmd.Val())}

pipeline通过redis.Pipeline() 创建,使用管道对象添加命令,最后调用Exec() 执行。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/51431.html

  • 返回的cmds包含每个命令的响应,可以依次处理。
  • 这样就可以批量的发送多个命令,优化访问Redis服务器。

访问Redis集群

func clusterDemo() {
    // 集群节点,可以填一个或者多个    // go-redis通过部分节点获取整个集群拓扑(所有节点信息)    client := redis.NewClusterClient(&redis.ClusterOptions{        Addrs: []string{            "127.0.0.1:7000",            "127.0.0.1:7001",             "127.0.0.1:7002",        },    })
    err := client.Set("key", "value", 0).Err()    if err != nil {        panic(err)    }
    val, err := client.Get("key").Result()    if err != nil {        panic(err)    }    fmt.Println("key", val)
    err = client.Close()    if err != nil {        panic(err)    }}
  • 通过NewClusterClient创建客户端,传入集群节点地址。
  • 然后就可以像使用单机客户端一样,直接操作集群了。
  • go-redis会自动将请求路由到正确的节点上。
  • 因此go-redis可以非常容易地访问Redis集群

事务(transaction)

func transactionDemo(client *redis.Client) {
  pipe := client.TxPipeline()
  pipe.Set("key1", "value1", 0)  pipe.Set("key2", "value2", 0)
  _, err := pipe.Exec()  if err != nil {    panic(err)  }
}
  • 使用TxPipeline() 创建一个事务管道。
  • 然后将命令添加到管道中,最后调用Exec() 执行。
  • 这会将所有命令作为一个事务(transaction)发送到Redis服务器。

需要注意的是,Redis中的事务(transaction)不是一个原子操作。它只是一种将多个命令打包然后顺序执行的机制。与关系型数据库的事务不同,Redis事务中若某个命令执行失败, 后续的命令将不会继续执行, 但是不会回滚整个事务。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/51431.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/bc/51431.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定