【问题标题】:SETEX error - "Use of closed network connection"SETEX 错​​误 - “使用关闭的网络连接”
【发布时间】:2015-12-09 22:49:19
【问题描述】:

我正在使用以下代码从我的 Go 应用程序中执行 SET 和 EXPIRE。

_, err = C.Cache.Do("SETEX", key, 3600, data)

但我开始遇到错误:使用关闭的网络连接。我使用 Gary Burd 的 Redigo 包和 RedisLabs。

我连接 Redis 的代码是:

//Connect to cache (Redis)
cache, err := connectToCache()
if err != nil {
    log.Printf("Cache connection settings are invalid")
    os.Exit(1)
}
defer cache.Close()

func connectToCache() (redis.Conn, error) {
    cache, err := redis.Dial("tcp", CACHE_URI)
    if err != nil {
        return nil, err
    }
    _, err = cache.Do("AUTH", CACHE_AUTH)
    if err != nil {
        cache.Close()
        return nil, err
    }
    return cache, nil
}

【问题讨论】:

  • 如果您收到有关关闭连接的错误,您需要重新连接到数据库。不应该与 SETEX 命令有任何关系(顺便说一下,在较新的版本中通过使用带有选项的 SET 来取代它)
  • 我已经添加了我的代码来展示我如何管理 Redis 连接 - 它有任何明显的问题吗?感谢您提供有关 SET(带选项)命令的信息。
  • 我无法从代码中断章取义地判断延迟将发生在哪里,但您应该保持连接并尽可能重用它们。通常你想要一个redis.Pool。也可以在这里查看我的答案:stackoverflow.com/questions/30244080/…
  • 太棒了 - 我不确定什么时候需要一个游泳池,但我想是现在。
  • 如果@JimB 的回答不起作用,则使用race detector 运行应用程序并阅读Redigo 文档regarding concurrency

标签: go redis


【解决方案1】:

您可以使用redis.Pool 管理多个连接,检查空闲连接是否处于活动状态,并自动获取新连接。您还可以在拨打新连接时自动执行 AUTH 步骤:

func newPool(server, password string) *redis.Pool {
    return &redis.Pool{
        MaxIdle: 3,
        IdleTimeout: 240 * time.Second,
        Dial: func () (redis.Conn, error) {
            c, err := redis.Dial("tcp", server)
            if err != nil {
                return nil, err
            }
            if _, err := c.Do("AUTH", password); err != nil {
                c.Close()
                return nil, err
            }
            return c, err
        },
        TestOnBorrow: func(c redis.Conn, t time.Time) error {
            _, err := c.Do("PING")
            return err
        },
    }
}

var (
    pool *redis.Pool
    redisServer = flag.String("redisServer", ":6379", "")
    redisPassword = flag.String("redisPassword", "", "")
)

func main() {
    flag.Parse()
    pool = newPool(*redisServer, *redisPassword)
    ...
}

【讨论】:

  • 所以正如您在另一个答案中指出的那样,我每次需要新连接时都使用conn = pool.Get() 之类的东西?
  • @tommyd456:是的,每次需要连接时都调用pool.Get(),然后调用conn.Close 将连接返回到池中。
  • 我认为推迟关闭操作是可取的
  • 另外,由于这是我正在制作的 API - 每次在 Redis 操作本身之前命中路由时,我是否会创建连接?
  • @tommyd456:是的,您需要确保调用 Close,否则连接不会返回到池中。当您需要连接时,您会从池中获取连接,并在完成后返回它。
猜你喜欢
  • 1970-01-01
  • 2021-12-10
  • 2017-05-24
  • 2023-03-25
  • 2012-02-17
  • 2015-02-27
  • 1970-01-01
  • 2010-12-24
  • 2021-01-25
相关资源
最近更新 更多