【发布时间】:2016-09-07 19:33:03
【问题描述】:
我已通读完整的 Redigo 文档,可在此处找到。 https://godoc.org/github.com/garyburd/redigo/redis#pkg-variables
这里的文档明确指出连接不支持并发调用 Send()、Flush() 或 Receive() 方法。
连接不支持并发调用写入方法 (发送、刷新)或并发调用读取方法(接收)。 连接确实允许并发读取器和写入器。
然后它指出,由于 Do 方法可以是 Send()、Flush() 和 Receive() 的组合,所以我们不能同时使用 Do()(与)其他方法。
因为 Do 方法结合了 Send、Flush 和 接收,Do方法不能与其他同时调用 方法。
这是否意味着我们可以使用存储在全局变量中的单个连接同时单独使用 Do(),只要我们不将它与其他方法混合使用?
例如这样:
var (
// Redis Conn.
redisConn redis.Conn
// Redis PubSubConn wraps a Conn with convenience methods for subscribers.
redisPsc redis.PubSubConn
)
func redisInit() {
c, err := redis.Dial(config.RedisProtocol, config.RedisAddress)
if err != nil {
log.Fatal(err)
}
c.Do("AUTH", config.RedisPass)
redisConn = c
c, err = redis.Dial(config.RedisProtocol, config.RedisAddress)
if err != nil {
log.Fatal(err)
}
c.Do("AUTH", config.RedisPass)
redisPsc = redis.PubSubConn{c}
for {
switch v := redisPsc.Receive().(type) {
case redis.Message:
// fmt.Printf("%s: message: %s\n", v.Channel, v.Data)
socketHub.broadcast <- v.Data
case redis.Subscription:
// fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)
case error:
log.Println(v)
}
}
}
然后在一些 go 例程中调用 Do() 方法,如下所示:
if _, err = redisConn.Do("PUBLISH", fmt.Sprintf("user:%d", fromId), message); err != nil {
log.Println(err)
}
if _, err = redisConn.Do("PUBLISH", fmt.Sprintf("user:%d", toId), message); err != nil {
log.Println(err)
}
然后文档说,为了对 Redis 进行完全并发访问,我们需要创建一个池并从池中获取连接,并在完成后释放它们。
这是否意味着只要我从池中获得连接,我就可以随意使用 Send()、Flush() 和 Receive()?所以换句话说,每次我需要在 go 例程中做某事时,我都必须从池中获取新连接,而不是重用全局连接?这是否意味着只要我从池中获得新连接,我就可以将 Do() 方法与例如 Send() 一起使用?
总结一下:
1) 我可以同时使用 Do() 方法,只要我不将它与 Send、Flush 和 Receive 方法一起使用吗?
2) 只要我从池中获得新连接并在完成后释放它,我就可以随意使用所有内容吗?
3) 如果 (1) 为真,这会影响性能吗?在我提供的示例中,仅使用 Do() 方法同时使用全局连接,而不是与 Send、Flush 和 Receive 混合使用会更好吗?
【问题讨论】: