1

I am getting the below error.

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)

Node.js with MySQL db and redis concept is used. There are too many requests for fetching the data from MySQL so data is cached for 2 minutes by syncing with db. So when new requests arrives it checks in redis if found its serves from redis else data is retrieved from MySQL and cached in redis and sent as response. This keeps happening.

After some time probably 1 hour or 2 hours the server crashes resulting in above error. But as of now pm2 is used which restarts the server.

But need to know the reason for it.

Redis installation followed the instructions from here. https://www.digitalocean.com/community/tutorials/how-to-install-and-use-redis

Snapshot

Please let me know how to solve the issue...

Redis Connection File Code

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;
        }
    }
};
Sharath
  • 2,348
  • 8
  • 45
  • 81
  • This is not a MySQL question. Please tag *only* the relevant things. – tadman Mar 01 '17 at 18:22
  • sorry @tadman for tagging mysql – Sharath Mar 01 '17 at 18:23
  • It looks like your Redis server is dead. Can you poke it to see if it's alive? – tadman Mar 01 '17 at 18:24
  • I have put the snapshot of it in the question. After it restarts it works normal but again after 1 or 2 hour it crashes and this repeats continuously. – Sharath Mar 01 '17 at 18:32
  • actually its just a info about the redis in snapshot. But as per your question i tried redis-cli then i am able to run redis commands which works. – Sharath Mar 01 '17 at 18:41
  • @tadman do you need any other information regarding this. – Sharath Mar 01 '17 at 18:53
  • @tadman redis and node.js is installed on same machine. So i am trying to connect to localhost, – Sharath Mar 02 '17 at 07:08
  • @tadman i have put redis connection code in the question. Should i update it by removing the port no – Sharath Mar 02 '17 at 07:44
  • This might be related to [this problem](http://stackoverflow.com/questions/10355501/connect-emfile-error-in-node-js) if you're creating too many connections, like over 1000. – tadman Mar 02 '17 at 07:47
  • i haven't tried with no arguments in createClient(), wait i'll check it – Sharath Mar 02 '17 at 07:48
  • I have a feeling you're not properly closing all these connections you make and your program tanks when you create too many. Your code also tests that the connection is not valid, and then tries to end it? That's probably going to crash too. – tadman Mar 02 '17 at 07:48
  • ok let me check in all the places if I am closing it. – Sharath Mar 02 '17 at 07:53
  • probably as you said if(!redisClient) redisClient.end(); condition might not be required right. – Sharath Mar 02 '17 at 07:55

1 Answers1

1

What I usually do with code like this is write a very thin module that loads in the correct Redis driver and returns a valid handle with a minimum of fuss:

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();
  }
};

Any code in your Node application that needs a Redis handle acquires one on-demand and it's also understood that code must close it no matter what happens. If you're not catching errors, or if you're catching errors and skipping the close you'll "leak" open Redis handles and your app will eventually crash.

So, for example:

 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);
   });
 }

Due to the concurrent nature of Node code having a single Redis handle that's shared by many different parts of code will be trouble and I'd strongly advise against this approach.

To expand on this template you'd have a JSON configuration file that can override which port and server to connect to. That's really easy to require and use instead of the defaults here. It also means that you don't have to hack around with any actual code when you deploy your application to another system.

You can also expand on the wrapper module to keep active connections in a small pool to avoid closing and then immediately opening a new one. With a little bit of attention you can even check that these handles are in a sane state, such as not stuck in the middle of a MULTI transaction, before handing them out, by doing a PING and testing for an immediate response. This weeds out stale/dead connections as well.

tadman
  • 208,517
  • 23
  • 234
  • 262