Re-using Redigo connection instead of recreating it every time
Asked Answered
C

2

7

Connecting to Redigo and manipulating data inside a function is easy like butter, but the problem comes when you have to re-use its connection, obviously for performance/practicality reasons.

Doing it inside a function like this works:

func main() {

    client, err := redis.Dial("tcp", ":6379")
    if err != nil {
        panic(err)
    }
    defer client.Close()

    client.Do("GET", "test:1")
}

But bringing it outside doesn't:

var Client = redis.Dial("tcp", ":6379")
defer Client.Close()

func main() {

        Client.Do("GET", "test:1")
    }

With the following error(s) returned:

./main.go:1: multiple-value redis.Dial() in single-value context
./main.go:2: non-declaration statement outside function body

I've tried putting the connection as a const(ant), putting defer inside the main function to my dismay not working too.

This is an even bigger concern as I have many other functions that have to communicate to Redis, but recreating the connection to Redis everytime seems silly.

The Redigo API just shows how to create a Dial instance but doesn't go further by explaining how to re-use it.

You may've been lost in my talk, but I wanted to put a bit of context here, so my clear and concise question is: How do you go about re-using (not recreating everytime) a Redigo connection?

Cower answered 24/6, 2014 at 13:1 Comment(1)
why not use redigo pools?Fahy
C
21

The best way turned out to be using Pools, which are briefly documented here: Redigo Pools.

A global variable won't eventually reuse a connection, so I ended up with something like this (using Pools as noted before):

func newPool() *redis.Pool {
return &redis.Pool{
            MaxIdle: 80,
            MaxActive: 12000, // max number of connections
            Dial: func() (redis.Conn, error) {
                    c, err := redis.Dial("tcp", ":6379")
                    if err != nil {
                            panic(err.Error())
                    }
                    return c, err
            },
    } 

}

var pool = newPool()

func main() {

        c := pool.Get()
        defer c.Close()

        test,_:=c.Do("HGETALL", "test:1")
        fmt.Println(test)
}

If for example you want to reuse a pool inside another function you do it like this:

func test() {
        c := pool.Get()
        defer c.Close()

        test2,_:=c.Do("HGETALL", "test:2")
        fmt.Println(test2)
}
Cower answered 24/6, 2014 at 13:57 Comment(2)
Why the Dial function is calling panic? Shouldn't the decision of how to deal with the error be left to the user?Obsessive
@Obsessive is correct. The dial function should not panic. Use Dial: func() (redis.Conn, error) { return redis.Dial("tcp", ":6379") }Behka
N
-1

The redis.Dial() method returns client error. To fix it, you should replace:

var Client = redis.Dial("tcp", ":6379") 

with:

var Client, _ = redis.Dial("tcp", ":6379")
Neau answered 27/5, 2016 at 2:11 Comment(1)
No, you should not do that, but handle the error instead of ignoring it.Constitutional

© 2022 - 2024 — McMap. All rights reserved.