Redigo:redis服务器关闭时失败

时间:2017-06-21 12:19:45

标签: go redis redigo

当我连接的redis服务器发生故障时,我很难快速失败,想要有一个强大的解决方案。

我正在使用redigo而我正在设置连接池,如下所示:

// This has other stuff in it in the code, use it as a 
// central repository for things we want in memory
type State struct{
    redisPool *redis.Pool
}

func (state *State) GetRedisConn() redis.Conn {
    return state.redisPool.Get()
}

func main() {
    state.redisPool = &redis.Pool{
        MaxIdle:     200,
        MaxActive:   9000,
        IdleTimeout: time.Minute,
        Dial: func() (redis.Conn, error) {
            return redis.Dial("tcp", *redisAddress,
                redis.DialConnectTimeout(1*time.Second),
                redis.DialReadTimeout(100*time.Millisecond),
                redis.DialWriteTimeout(100*time.Millisecond),
            )
        },
    }
}

请求新连接并使用它们如下:

t0 := time.Now()

conn := state.GetRedisConn()
if conn != nil && conn.Err() == nil {
    defer conn.Close()
    // Do stuff
else {
    log.Printf("no redis probably")
}

log.Println(time.Now().Sub(t0).Seconds())

当redis启动时,这很好用,事情发生在毫秒之内。我把redis降到第75个百分点的那一刻上升到7秒以上,我的第99个百分位上升到10个(我可以在普罗米修斯看到这个)

我做错了什么?为什么这不会超时更快? 我的印象是redis.DialConnectTimeout(1*time.Second)会在1秒内限制问题,但似乎并非如此。

编辑:事实证明这是由于我在普罗米修斯制造的一个错误,将水桶设置得太大,所以当redis在一秒钟之后超时时,我的水桶已经安装了1s水桶和10s因此,我的请求(刚好超过1秒)最终落入10s桶中,结果出现偏差。我确信这个讨论在某些方面对某些人有用。

1 个答案:

答案 0 :(得分:0)

失败后的速率限制拨号尝试:

func main() {
    var (
       nextDial time.Time
       mu sync.Mutex
    )
    state.redisPool = &redis.Pool{
        MaxIdle:     200,
        MaxActive:   9000,
        IdleTimeout: time.Minute,
        Dial: func() (redis.Conn, error) {
            mu.Lock()   // Dial can be called concurrently
            defer mu.Unlock()
            if time.Now().Before(nextDial) {
               return nil, errors.New("waiting for dial")
            }
            c, err := redis.Dial("tcp", *redisAddress,
                redis.DialConnectTimeout(1*time.Second),
                redis.DialReadTimeout(100*time.Millisecond),
                redis.DialWriteTimeout(100*time.Millisecond),
            )
            if err == nil {
               nextDial = time.Time{}
            } else {
               nextDial = time.Now().Add(time.Second) // don't attempt dial for one second
            }
            return c, err
        },
    }
}