Golang+Gin+ Redis Cluster

最近用redis shake做redis数据迁移,由于redis提供的客户端没有用于查看集群的工具,且我部署的redis集群是基于k8s来构建的,没有使用ingress做转发,所以只能在k8s内部访问集群,于是我先用go+gin框架编写了访问redis集群的代码,然后打成镜像,再部署到k8s中,创建一个svc类型为NodePort方便外部访问。

环境搭建完毕后,访问接口,发现连接redis集群失败,报错:

dial tcp: lookup redis-cluster-v2-0.redis-cluster-v2.redis: i/o timeout

我尝试在容器内部ping | telnet redis集群某一结点地址,发现网络是可通的,后面在代码中新增net.dail()去连接redis集群,报另一个错误:

 got 4 elements in cluster info address, expected 2 or 3

发现使用的go redis版本与redis的版本不一致造成的,

  • Redis 6.0及以下版本:选择Go-redis v8.0及以下版本。

  • Redis 7.0及以上版本:选择Go-redis v9.0及以上版本。

由于我部署的redis集群是7.0,但go redis使用的版本是 v8["github.com/go-redis/redis/v8"],于是修改go redis版本:

"github.com/redis/go-redis/v9"
复制代码
package main

import (
    "context"
    "fmt"
    "github.com/redis/go-redis/v9"
    "strconv"
    "testing"
    "time"
)

func TestRedis(t *testing.T) {
    client := redis.NewClusterClient(&redis.ClusterOptions{
        Addrs: []string{
            "localhost:6371",
            "localhost:6372",
            "localhost:6373",
            "localhost:6374",
            "localhost:6375",
            "localhost:6376",
        },
        Password:      "ruiec.com", // 在这里设置你的Redis实例密码
        RouteRandomly: true,        // 启用随机路由,以实现负载均衡
    })
    // 记录开始时间
    start := time.Now()
    for i := 0; i < 100000; i++ {
        // 使用客户端发送Redis命令
        ctx := context.Background()
        err := client.Set(ctx, "name"+strconv.Itoa(i), "张三"+strconv.Itoa(i), 0).Err()
        if err != nil {
            panic(err)
        }

        val, err := client.Get(ctx, "name"+strconv.Itoa(i)).Result()
        if err != nil {
            panic(err)
        }
        fmt.Println("key", val)
    }
    // 记录结束时间
    end := time.Now()
    // 打印代码运行时长
    fmt.Printf("TestRedis代码运行时长: %v\n", end.Sub(start))
}
复制代码

使用协程的方式:

复制代码
package main

import (
    "context"
    "fmt"
    "github.com/redis/go-redis/v9"
    "strconv"
    "sync"
    "testing"
    "time"
)

func TestGoroutineRedis(t *testing.T) {
    client := redis.NewClusterClient(&redis.ClusterOptions{
        Addrs: []string{
            "localhost:6371",
            "localhost:6372",
            "localhost:6373",
            "localhost:6374",
            "localhost:6375",
            "localhost:6376",
        },
        Password:      "1234", // 在这里设置你的Redis实例密码
        RouteRandomly: true,        // 启用随机路由,以实现负载均衡
    })
    // 记录开始时间
    start := time.Now()
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go insertGoroutineRedis(client, &wg)
    }
    wg.Wait()
    // 记录结束时间
    end := time.Now()
    // 打印代码运行时长
    fmt.Printf("insertGoroutineRedis代码运行时长: %v\n", end.Sub(start))
}
func insertGoroutineRedis(client *redis.ClusterClient, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 100000; i++ {
        // 使用客户端发送Redis命令
        ctx := context.Background()
        err := client.Set(ctx, "name"+strconv.Itoa(i), "张三"+strconv.Itoa(i), 0).Err()
        if err != nil {
            panic(err)
        }

        val, err := client.Get(ctx, "name"+strconv.Itoa(i)).Result()
        if err != nil {
            panic(err)
        }
        fmt.Println("key", val)
    }
}
复制代码

使用协程+通道方式

复制代码
package main

import (
    "context"
    "fmt"
    "github.com/redis/go-redis/v9"
    "strconv"
    "sync"
    "testing"
    "time"
)

func TestGoroutineChannelRedis(t *testing.T) {
    client := redis.NewClusterClient(&redis.ClusterOptions{
        Addrs: []string{
            "localhost:6371",
            "localhost:6372",
            "localhost:6373",
            "localhost:6374",
            "localhost:6375",
            "localhost:6376",
        },
        Password:      "1234", // 在这里设置你的Redis实例密码
        RouteRandomly: true,        // 启用随机路由,以实现负载均衡
    })
    // 记录开始时间
    start := time.Now()
    fmt.Println(start)
    var wg sync.WaitGroup
    // 创建一个缓冲channel,用于并发插入数据
    ch1 := make(chan int, 1000000)
    // 将100000个值放入channel中
    for i := 0; i < 1000000; i++ {
        ch1 <- i
    }
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for j := 0; j < 100000; j++ {
                // 从channel中取出一个值插入到Redis Cluster中
                key := <-ch1
                // 使用客户端发送Redis命令
                ctx := context.Background()
                err := client.Set(ctx, "name"+strconv.Itoa(key), "张三"+strconv.Itoa(key), 0).Err()
                if err != nil {
                    fmt.Println("Error inserting value:", err)
                }
            }
        }()
    }
    close(ch1)
    wg.Wait()
    // 记录结束时间
    end := time.Now()
    fmt.Println(end)
    // 打印代码运行时长
    fmt.Printf("insertGoroutineChannelRedis代码运行时长: %v\n", end.Sub(start))
}
复制代码

 

posted @   ParallelForEach  阅读(684)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示