【问题标题】:Error: Redis connection to localhost:6379 failed - getaddrinfo EMFILE localhost:6379错误:与 localhost:6379 的 Redis 连接失败 - getaddrinfo EMFILE localhost:6379
【发布时间】:2017-07-21 05:14:33
【问题描述】:

我收到以下错误。

Error: Redis connection to localhost:6379 failed - getaddrinfo EMFILE localhost:6379
at Object.exports._errnoException (util.js:870:11)
at errnoException (dns.js:32:15)
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:78:26)

使用了带有 MySQL db 和 redis 概念的 Node.js。 从 MySQL 获取数据的请求太多,因此通过与 db 同步将数据缓存 2 分钟。因此,当新请求到达时,它会检查 redis 是否从 redis 中找到它的服务,否则会从 MySQL 检索数据并缓存在 redis 中并作为响应发送。这种情况一直在发生。

大约 1 小时或 2 小时后,服务器崩溃导致上述错误。 但截至目前,使用 pm2 重新启动服务器。

但需要知道它的原因。

Redis 安装按照此处的说明进行。 https://www.digitalocean.com/community/tutorials/how-to-install-and-use-redis

请告诉我如何解决这个问题...

Redis 连接文件代码

var Promise = require('bluebird');
var redisClient;        // Global (Avoids Duplicate Connections)

module.exports = 
{
    OpenRedisConnection : function()
    {
        if (redisClient == null) 
        {
            redisClient = require("redis").createClient(6379, 'localhost');
            redisClient.selected_db = 1;
        }
    },
    GetRedisMultiConnection: function () 
    {
        return require("redis").createClient(6379, 'localhost').multi();       
    },
    IsRedisConnectionOpened : function()
    {
        if (redisClient && redisClient.connected == true) 
        {
            return true;
        }
        else 
        {
            if(!redisClient)
                redisClient.end();  // End and open once more

            module.exports.OpenRedisConnection();

            return true;
        }
    }
};

【问题讨论】:

  • 这不是 MySQL 问题。请只标记相关的东西。
  • 对不起@tadman 标记mysql
  • 看起来你的 Redis 服务器已经死了。你能戳它看看它是不是还活着吗?
  • 我已将它的快照放在问题中。重新启动后它可以正常工作,但在 1 或 2 小时后再次崩溃,并且不断重复。
  • 实际上它只是关于快照中redis的信息。但是根据您的问题,我尝试了 redis-cli 然后我能够运行有效的 redis 命令。

标签: node.js redis


【解决方案1】:

我通常对这样的代码做的是编写一个非常薄的模块,该模块加载到正确的 Redis 驱动程序中,并以最少的麻烦返回一个有效的句柄:

var Redis = require("redis");

module.exports = {
  open: function() {
    var client = Redis.createClient(6379, 'localhost');
    client.selected_db = 1;

    return client;
  },
  close: function(client) {
    client.quit();
  }
};

您的 Node 应用程序中任何需要 Redis 句柄的代码都会按需获取一个句柄,并且也可以理解代码必须关闭它,无论发生什么。如果您没有发现错误,或者如果您发现错误并跳过关闭,您将“泄漏”打开的 Redis 句柄,您的应用最终会崩溃。

所以,例如:

 var Redis = require('./redis'); // Path to module defined above

 function doStuff() {
   var redis = Redis.open();

   thing.action().then(function() {
     redis.ping();
   }).finally(function() {
     // This code runs no matter what even if there's an exception or error
     Redis.close(redis);
   });
 }

由于 Node 代码的并发特性,具有由许多不同代码部分共享的单个 Redis 句柄会很麻烦,我强烈建议不要使用这种方法。

要扩展此模板,您将拥有一个 JSON 配置文件,该文件可以覆盖要连接的端口和服务器。 require 和使用这里的默认值真的很容易。这也意味着当您将应用程序部署到另一个系统时,您不必修改任何实际代码。

您还可以扩展包装器模块以将活动连接保留在一个小池中,以避免关闭然后立即打开一个新连接。稍加注意,您甚至可以通过执行PING 并测试立即响应来检查这些句柄是否处于正常状态,例如没有卡在MULTI 事务的中间,然后再分发它们.这也消除了陈旧/死的连接。

【讨论】:

  • 感谢@tadman,我会检查并回复您。
猜你喜欢
  • 2014-11-07
  • 1970-01-01
  • 2017-07-06
  • 2020-03-13
  • 2017-05-16
  • 2020-08-27
  • 1970-01-01
  • 1970-01-01
  • 2019-01-03
相关资源
最近更新 更多