You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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持久化、主从同步等耗时操作时,可能无法及时处理客户端的请求,导致请求写入过程中断,进而出现该错误。

  • 连接池中的连接处于异常状态
    如果之前使用该连接的代码没有正确处理错误,导致连接处于异常状态(比如之前的请求已经失败但未标记连接失效),归还到连接池后被复用,也会引发这类写入错误。

排查建议

  1. 在连接池配置中添加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
    },
    
  2. 检查Redis服务端的timeout配置,确保其值大于客户端连接池的IdleTimeout,避免服务端主动断开空闲连接。
  3. 查看Redis服务端日志,确认是否存在超时、内存不足、持久化异常等记录。
  4. 检查客户端与Redis服务端之间的网络连通性,比如使用ping、telnet工具测试链路稳定性。

内容的提问来源于stack exchange,提问作者Woody1193

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 04:20:31