我已经阅读了可以在此处找到的整个 Redigo 文档。 https://godoc.org/github.com/garyburd/redigo/redis#pkg-variables
这里的文档明确指出连接不支持并发调用 Send()、Flush() 或 Receive() 方法。
连接不支持并发调用写入方法(发送、刷新)或并发调用读取方法(接收)。连接确实允许并发读取器和写入器。
然后它指出,由于 Do 方法可以是 Send()、Flush() 和 Receive() 的组合,我们不能同时使用 Do()(与)其他方法。
由于 Do 方法结合了 Send、Flush 和 Receive 的功能,因此 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() 方法同时使用全局连接,而不是与发送、刷新和接收混为一谈,是否更好?