Golang: Selecting DB on a RedisPool in Redigo

huangapple go评论76阅读模式
英文:

Golang: Selecting DB on a RedisPool in Redigo

问题

使用redigo,我创建了一个连接池,类似于以下代码:

&redis.Pool{
    MaxIdle:   80,
    MaxActive: 12000, // 最大连接数
    Dial: func() (redis.Conn, error) {
        c, err := redis.Dial("tcp", host+":"+port)
        if err != nil {
            panic(err.Error())
        }
        return c, err
    }
}

我的问题是,每次获取一个新的连接时,我都需要设置数据库,因为我在VPS上托管了多个站点,每个站点使用不同的Redis数据库。

所以,类似于这样:

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

conn.Do("SELECT", dbNumber)  // 这是我想避免的调用

每次使用Redis时都需要选择数据库似乎是多余的,并且还存在一个问题,因为我将其用于会话,即使不是我的代码与我的Redis连接池一起工作,也无法为其设置正确的数据库。

我想要做的是为连接池设置数据库编号,这样每当有人从连接池请求一个新的连接时,它就已经设置了正确的数据库,即不需要每次显式设置。

你是如何在你的应用程序中解决这个问题的?

谢谢。

英文:

using redigo, I create a pool, something like so:

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

the problem I have is that for each time I get a new connection, I need to set the db, as I use different db's of redis since I host a number of sites on the VPS.

So, something like this:

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

conn.Do("SELECT", dbNumber)  //this is the call I want to avoid

Having to select the db each time I work with redis seems redundant and also poses a problem since I use it for sessions i.e. having code that is not mine working with my redis connection from my pool makes it "impossible" to set the correct db for it.

What I would like to do is to set the dbno for the pool so that whenever somebody asks for a new connection from the pool, it comes with the correct db already set i.e. not setting it explicitly each time.

How did you solve this in your applications?

Thanks.

答案1

得分: 9

你可以使用redis.DialOptionredis.DialDatabaseredis.DialPassword

conn, err := redis.Dial("tcp", "127.0.0.1:6379", redis.DialDatabase(1))
if err != nil {
	panic(err)
}
defer conn.Close()
英文:

You can use redis.DialOption: redis.DialDatabase, redis.DialPassword

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

答案2

得分: 5

在你的拨号函数中选择数据库:

&redis.Pool{
    MaxIdle:   80,
    MaxActive: 12000, // 最大连接数
    Dial: func() (redis.Conn, error) {
        c, err := redis.Dial("tcp", host+":"+port)
        if err != nil {
            return nil, err
        }
        _, err := c.Do("SELECT", dbNum)
        if err != nil {
           c.Close()
           return nil, err
        }
        return c, nil
    }
}

此外,返回拨号错误而不是发生恐慌。

英文:

Select the database in your dial function:

&redis.Pool{
    MaxIdle:   80,
    MaxActive: 12000, // max number of connections
    Dial: func() (redis.Conn, error) {
        c, err := redis.Dial("tcp", host+":"+port)
        if err != nil {
            return nil, err
        }
        _, err := c.Do("SELECT", dbNum)
        if err != nil {
           c.Close()
           return nil, err
        }
        return c, nil
    }

Also, return the error from dial instead of panicking.

答案3

得分: 2

如果这些库不支持此功能,那么你有两个选择:

  1. 提交一个补丁来自动化这个过程(Python库已经这样做了,但在保持状态时要小心)。

  2. 使用自定义池包装你自己的 Redis 池,实现自动化(下面是一个示例代码,未经测试,但你可以理解其中的思路):

// 嵌入原始池并添加 dbno 状态的池
type DbnoPool struct {
    redis.Pool
    dbno int
}

// “覆盖” Get 方法
func (p *DbnoPool) Get() Connection {
    conn := p.Pool.Get()
    conn.Do("SELECT", p.dbno)
    return conn
}

pool := &DbnoPool{
    redis.Pool{
        MaxIdle:   80,
        MaxActive: 12000, // 最大连接数
        Dial: func() (redis.Conn, error) {
            c, err := redis.Dial("tcp", host+":"+port)
            if err != nil {
                panic(err.Error())
            }
            return c, err
        },
    },
    3, // 数据库编号
}

// 现在你可以正常调用它
conn := pool.Get()
defer conn.Close()

希望对你有帮助!

英文:

If these libs don't support it, then you have two options:

  1. submit a patch to automate this (the python lib does that, but be careful when keeping the state).

  2. Wrap your redis pool with your own custom pool that automates this, something like (untested code, but you'll get the idea):

         // a pool embedding the original pool and adding adbno state
         type DbnoPool struct {
     	   redis.Pool
     	   dbno int
     	}
    
    
     	// "overriding" the Get method
     	func (p *DbnoPool)Get() Connection {
     	   conn := p.Pool.Get()
     	   conn.Do("SELECT", p.dbno)
     	   return conn
     	}
    
     	pool := &DbnoPool {
     	    redis.Pool{
     	        MaxIdle:   80,
     	        MaxActive: 12000, // max number of connections
     	        Dial: func() (redis.Conn, error) {
     	        c, err := redis.Dial("tcp", host+":"+port)
     	        if err != nil {
     	            panic(err.Error())
     	        }
     	        return c, err
     	    },
     	    3, // the db number
     	}
    
     	//now you call it normally
     	conn := pool.Get()
     	defer conn.Close()
    

答案4

得分: 0

最好的方法是使用DialOption,例如DialDatabase

redisPool = &redis.Pool{
    MaxIdle:     AppConfig.DefaultInt("RedisMaxPool", 10),
    IdleTimeout: 240 * time.Second,
    
    Dial: func() (redis.Conn, error) {
        c, err := redis.Dial(
            "tcp",
            AppConfig.DefaultString("RedisPath", ":6379"),
            redis.DialDatabase(AppConfig.DefaultInt("RedisDB", 1)),
        )
        if err != nil {
            return nil, err
        }
        return c, err
    },
    
    TestOnBorrow: func(c redis.Conn, t time.Time) error {
        _, err := c.Do("PING")
        return err
    },
}
英文:

Best way is to use DialOptions like DialDatabase:

redisPool = &redis.Pool{
	
	MaxIdle:     AppConfig.DefaultInt("RedisMaxPool", 10),
	IdleTimeout: 240 * time.Second,
	
	Dial: func() (redis.Conn, error) {
		c, err := redis.Dial(
			"tcp",
			AppConfig.DefaultString("RedisPath", ":6379"),
			redis.DialDatabase(AppConfig.DefaultInt("RedisDB", 1)),
		)
		if err != nil {
			return nil, err
		}
		return c, err
	},
	
	TestOnBorrow: func(c redis.Conn, t time.Time) error {
		_, err := c.Do("PING")
		return err
	},
}

huangapple
  • 本文由 发表于 2014年9月7日 16:09:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/25708256.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定