【问题标题】:go/golang + redis too many open files errorgo/golang + redis 打开文件太多错误
【发布时间】:2013-11-14 07:29:29
【问题描述】:

我在 Golang 中使用 Redis 和 Redis 网站建议的 Redigo 连接器 (https://github.com/garyburd/redigo)。

我有:

  • 每次 Dial() 后,我都会推迟 Close()
  • 设置 fs.file-max = 100000
  • 设置 vm.overcommit_memory = 1
  • 已禁用保存
  • 设置 maxclients = 100000

我经营一个高流量的网站,一切都运行良好大约 10 分钟,我从中得到

error: dial tcp 127.0.0.1:6379: too many open files

那么我的应用程序根本无法访问redis。

我在 redis 日志中看不到任何错误或问题。我该怎么做才能解决这个问题?

【问题讨论】:

标签: redis go


【解决方案1】:

我不知道您使用哪个驱动程序,但是使用 redigo 您可以在池中定义多个打开的连接,然后您所要做的就是在对 redis 的每个查询中,首先从池中获取一个客户端,然后关闭它,让它回到池中并被重新使用,就像这样:

redisPool = &redis.Pool{
        MaxIdle: 3,
        MaxActive: 10, // max number of connections
        Dial: func() (redis.Conn, error) {
                c, err := redis.Dial("tcp", ":6379")
                if err != nil {
                        panic(err.Error())
                }
                return c, err
        },
}
r := redisPool.Get() // get a client from the pool
_, err = r.Do("GET one") // use the client
if err != nil {
        panic(err.Error())
}
r.Close() // close the client so the connection gets reused

【讨论】:

  • 非常感谢!!太棒了!!这是否意味着在做一个 HTTP Web 应用程序时,我应该创建一个指向池的全局指针?然后从这个全局指针中拉取。
  • 我想是的,看不出它有什么影响。如果你想在代码的某些部分包含访问权限,那么你可以在不同的上下文中创建不同的池,那应该没问题还有..
  • 关闭连接的更好方法是在r := redisPool.Get()之后defer r.Close()
  • 仅供参考,现在这是过时的答案,因为没有 redis.Pool
【解决方案2】:

您的问题是 Redis 无法打开新连接,然后变得无响应,您需要增加操作系统的文件描述符限制(ubuntu 默认为 1024,这可能是一个问题),这现在主导了 redis maxclients 设置。

你调整这个限制的方式取决于操作系统 redis 正在运行,在 linux 上你需要这样的东西:

ulimit -n 99999

【讨论】:

  • 这可能会暂时起作用,但是如果您运行程序足够长的时间,那么它可能会达到极限。提高 ulimit 的风险在于它适用于开发盒,但在生产中,请求率和运行时间更高,你会遇到问题。有时您需要提高 ulimit,因此您的回答对某些人有用,但就我而言,我需要防止打开这么多文件。
  • @thebiggestlebowski 我同意你的观点,如果你的程序泄漏连接或做错事,你应该修复它。话虽如此,大多数 Linux 上 1024 的最大限制非常低,许多在生产中运行的健康程序会因此而崩溃或更糟。
猜你喜欢
  • 2014-10-03
  • 1970-01-01
  • 2022-07-08
  • 1970-01-01
  • 2010-12-07
  • 1970-01-01
  • 1970-01-01
  • 2014-06-23
  • 2016-03-17
相关资源
最近更新 更多