Node.js Cluster Shared Cache
Asked Answered
T

1

5

I'm using node-cache to create a local cache, however, the problem I have is that when using the application with PM2 which creates an application cluster the cache is created multiple times, one for each process - this isn't too much of a problem as the cached data is small so memory isn't the issue.

The real problem that I have an API call to my application to flush the cache, however when calling this API it will only flush the cache for the particular process that handles that call.

Is there a way to signal all workers to perform a function?

I did think about using Redis to cache instead as that would make it simpler to only have the one cache, the problem I have with Redis is I'm not sure the best way to scale it, I've currently got 50 applications and wouldn't want to set-up a new Redis database for each application, the alternative was to use ioredis and it's transparent key prefixing for each application but this could cause some security vulnerabilities if one application was to accidentally read data from the other clients application - And I don't believe there is a way to delete all keys just for a particular prefix (i.e. one app/client) as FLUSHALL will remove all keys

What are best practices for sharing cache for clustered node instances, but where there are many instances of the application too - think SAAS application.

Currently, my workaround for this issue is using node-cron to clear the cache every 15mins, however, there are items in the cache that don't really ever change, and there are other items which should be updated as soon as an external tool signals the application to flush the cache via an API call

Tamah answered 29/12, 2019 at 20:42 Comment(1)
michal pavlik posted an Answer saying "You can try this package which can store data within processes: npmjs.com/package/pm2-cluster-cache"Daniels
T
6

For anyone looking at this, for my use case, the best method was to use IPC.

I implemented an IPC messenger to pass messages to all processes, I read in the process name from the pm2 config file (app.json) to ensure we send the message to the correct application

// Sender
// The sender can run inside or outside of pm2
var pm2 = require('pm2');
var cfg = require('../app.json');

exports.IPCSend = function (topic, message) {
    pm2.connect(function () {
        // Find the IDs of who you want to send to
        pm2.list(function (err, processes) {
            for (var i in processes) {
                if (processes[i].name == cfg.apps[0].name) {
                    console.log('Sending Message To Id:', processes[i].pm_id, 'Name:', processes[i].name)
                    pm2.sendDataToProcessId(processes[i].pm_id, {
                        data: {
                            message: message
                        },
                        topic: topic
                    }, function (err, res) {
                        console.log(err, res);
                    });
                }
            }

        });
    });

}


// Receiver
// No need to require require('pm2') however the receiver must be running inside of pm2
process.on('message', function (packet) {
    console.log(packet);
});
Tamah answered 9/4, 2020 at 8:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.