Go中Redis GET操作返回short write错误的原因排查
Redis GET操作返回"short write"错误的原因分析
你基于Go语言和Redis实现了跨进程的定时任务调度逻辑,核心代码如下:
核心调度函数
func doMasterInner(ctx context.Context, conn redis.Conn, suffix string, freq time.Duration, op func(context.Context) error) error { key := fmt.Sprintf("myserviced_%s", suffix) _, err := redis.Int(conn.Do("GET", key)) var shouldRun bool if err != nil { if err != redis.ErrNil { return fmt.Errorf("Failed to get %s from Redis, error: %v", key, err) } shouldRun = true if _, err := conn.Do("SETEX", key, int(freq.Seconds()), 0); err != nil { return fmt.Errorf("Failed to set timer for %s in Redis, error: %v", key, err) } } if shouldRun { return op(ctx) } return nil }
调用代码
pool := &redis.Pool{ MaxIdle: 3, MaxActive: 4, Wait: true, IdleTimeout: 240 * time.Second, Dial: func() (redis.Conn, error) { return redis.Dial("tcp", addr, redis.DialPassword(password), redis.DialConnectTimeout(5 * time.Second)) }, } conn := pool.Get() defer conn.Close() err := doMasterInner(context.Background(), conn, "assets", time.Hour, func(ctx context.Context) error { // do something here return nil }) fmt.Printf("Error: %v", err)
运行时出现错误:Failed to get myserviced_assets from Redis, error: short write,以下是这个错误的常见原因:
复用了失效的Redis连接
连接池中的空闲连接可能因为Redis服务端超时配置(比如timeout参数)、网络中断等原因已经断开,但客户端连接池未检测到,当你从池中获取并复用这个失效连接时,发送GET请求会因为连接不可用导致数据写入不完整,触发short write错误。
你的连接池设置了IdleTimeout: 240 * time.Second,如果Redis服务端的timeout值小于这个时间,服务端会先断开空闲连接,而客户端还会把它当作有效连接复用。网络链路异常
客户端与Redis服务端之间的网络存在丢包、带宽瓶颈或链路不稳定的情况,导致发送GET请求的数据包无法完整写入TCP连接,底层网络库会返回短写错误。Redis服务端负载过高或异常
当Redis服务端处于高CPU、高内存负载状态,或者正在执行RDB/AOF持久化、主从同步等耗时操作时,可能无法及时处理客户端的请求,导致请求写入过程中断,进而出现该错误。连接池中的连接处于异常状态
如果之前使用该连接的代码没有正确处理错误,导致连接处于异常状态(比如之前的请求已经失败但未标记连接失效),归还到连接池后被复用,也会引发这类写入错误。
排查建议
- 在连接池配置中添加
TestOnBorrow钩子,每次获取连接时先通过PING命令验证连接有效性:TestOnBorrow: func(c redis.Conn, t time.Time) error { // 如果连接空闲时间小于1分钟,直接返回有效 if time.Since(t) < time.Minute { return nil } // 否则执行PING检测 _, err := c.Do("PING") return err }, - 检查Redis服务端的
timeout配置,确保其值大于客户端连接池的IdleTimeout,避免服务端主动断开空闲连接。 - 查看Redis服务端日志,确认是否存在超时、内存不足、持久化异常等记录。
- 检查客户端与Redis服务端之间的网络连通性,比如使用
ping、telnet工具测试链路稳定性。
内容的提问来源于stack exchange,提问作者Woody1193
相关产品推荐
相关产品推荐

