Search code examples
goredispoolredigo

redigo different pool connect to single server


so, i have a necessity to connect to 3 redis server. i create 3 connection pool, and initialize each of them. but redigo seems only connected to single redis server, although i get the connection using different pool.

using redigo, here's my code below

import (
    "fmt"
    "time"
    "github.com/garyburd/redigo/redis"
)

var poolA *redis.Pool
var poolB *redis.Pool
var poolC *redis.Pool

func main() {
    poolA = &redis.Pool{}
    poolB = &redis.Pool{}
    poolC = &redis.Pool{}

    connections := []string{"localhost:6379", "localhost2:6379", "localhost3:6379"}

    for k, v := range connections {
        redisPool := &redis.Pool{
            Dial: func() (redis.Conn, error) {
                return redis.Dial("tcp", v)
            },
            TestOnBorrow: func(c redis.Conn, t time.Time) error {
                if time.Since(t) < time.Minute {
                    return nil
                }
                _, err := c.Do("PING")
                return err
            },
            IdleTimeout: time.Duration(10) * time.Second,
            MaxActive:   100,
            MaxIdle:     100 / 2,
            Wait:        true,
        }

        if k == 0 {
            fmt.Println("poolA:", v)
            poolA = redisPool
        }
        if k == 1 {
            fmt.Println("poolB:", v)
            poolB = redisPool
        }
        if k == 2 {
            fmt.Println("poolC:", v)
            poolC = redisPool
        }
    }

    con := poolA.Get()
    defer con.Close()
    count, err := redis.Int(con.Do("SADD", "any:test", 3246))
    if err != nil {
        fmt.Println("error querying redis:", err.Error())
    }
    fmt.Println("count=", count)

    con2 := poolB.Get()
    defer con2.Close()
    count, err = redis.Int(con2.Do("SADD", "any:test", 3246))
    if err != nil {
        fmt.Println("error querying redis:", err.Error())
    }
    fmt.Println("count=", count)

    con3 := poolC.Get()
    defer con3.Close()
    count, err = redis.Int(con3.Do("SADD", "any:test", 3246))
    if err != nil {
        fmt.Println("error querying redis:", err.Error())
    }
    fmt.Println("count=", count)
}

the problem is, all 3 pools are connecting to the last server/connection, resulting just as below. any idea?

poolA: localhost:6379
poolB: localhost2:6379
poolC: localhost3:6379
error querying redis: dial tcp: lookup localhost3: no such host
count= 0
error querying redis: dial tcp: lookup localhost3: no such host
count= 0
error querying redis: dial tcp: lookup localhost3: no such host
count= 0

Process finished with exit code 0

Solution

  • The dial functions use the single variable v. The functions use the last value assigned to v when called.

    To fix the problem, declare a variable inside the scope of the for loop and use that variable in the dial function:

    for k, v := range connections {
        v := v // Declare variable scoped inside for loop 
        redisPool := &redis.Pool{
            Dial: func() (redis.Conn, error) {
                return redis.Dial("tcp", v)  // uses variable scoped inside for loop
            },
        ...
    

    Separate from this issue, the pool settings don't make sense. Because the pool is configured to discard connections that have been idle for 10 seconds, the test on borrow function never pings the server.