使用go-redis从Redis取值时延迟持续升高的原因及解决方法
问题描述
当使用大量Go协程并发从Redis获取较大值(如100KB)时,会出现延迟持续升高的情况;同时运行多份该脚本实例(即使在不同客户端,非CPU受限)时,延迟升高速度更快,每个新增客户端都会拖慢其他客户端。按Redis的性能表现,这种小规模场景下不应出现该问题——redis-benchmark显示Redis可处理10万级连接且吞吐量极高,但当前仅使用1-5个连接。
单客户端运行脚本结果
0: time: 0ms, val size: 100000 1: time: 37ms, val size: 100000 12: time: 37ms, val size: 100000 13: time: 37ms, val size: 100000 38: time: 37ms, val size: 100000 133: time: 97ms, val size: 100000 145: time: 97ms, val size: 100000 77: time: 97ms, val size: 100000 . . . 979: time: 235ms, val size: 100000 914: time: 236ms, val size: 100000 957: time: 232ms, val size: 100000 980: time: 235ms, val size: 100000 958: time: 235ms, val size: 100000 954: time: 236ms, val size: 100000 913: time: 236ms, val size: 100000 921: time: 236ms, val size: 100000 961: time: 236ms, val size: 100000 976: time: 236ms, val size: 100000
测试脚本代码
package main import ( "fmt" "context" "time" "strings" "github.com/redis/go-redis/v9" ) var ctx = context.Background() func main() { // 创建Redis客户端 rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", DB: 5, }) // 在Redis中存储100KB的测试值 key := "some:test:key" value := strings.Repeat("a", 100000) err := rdb.Set(ctx, key, value, 0).Err() if err != nil { fmt.Println("设置值失败:", err) return } // 异步执行1000次获取操作,记录每次耗时 for i := 0; i < 1000; i++ { go func(i int) { t1 := time.Now() val, err := rdb.Get(ctx, key).Result() if err != nil { fmt.Println("获取值失败:", err) return } t2 := time.Now() fmt.Printf("%d: time: %vms, val size: %d\n", i, t2.Sub(t1).Milliseconds(), len(val)) }(i) } // 等待一段时间确保所有协程执行完毕 time.Sleep(2 * time.Second) }
内容的提问来源于stack exchange,提问作者Joram
相关产品推荐
相关产品推荐

