最近用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)) }
标签:strconv,err,Redis,redis,Golang,go,Gin,localhost From: https://www.cnblogs.com/lwhzj/p/17187483.html