如何将redis与节点js簇

时间:2018-03-15 08:05:58

标签: node.js redis

我一直在使用redis作为我的nodejs服务器的内存存储。 会议也通过redis进行管理。

目前我一直在做的是,每当我的服务器连接到它时,我都会刷新redis,这样每当服务器启动时都没有会话

像这样:

redisClient.on('connect', function () {
    redisClient.flushdb(function (err, succeeded) {
        logger.debug("redis db cleared on startup--", succeeded); // will be true if successfull
    });
});

我还将redis用于其他一些数据存储,例如queue

但现在我想在我的服务器上实现群集。

我的问题是,如果我有4个cores,我的服务器上将运行4个节点实例。

num_processes = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
var workers = [];

// Helper function for spawning worker at index 'i'.
var spawn = function(i) {
    console.log("spawing at index---",i);
    workers[i] = cluster.fork();
    console.log("----worker id-------", workers[i].id,"-------");
    // Optional: Restart worker on exit
    workers[i].on('exit', function(code, signal) {
        console.log(`code is ${code} and signal is ${signal}`)
        console.log(`worker ${workers[i].process.pid} died array index is ---${i}`);
        console.log('respawning worker', i);
        spawn(i);
    });
    workers[i].on('listening', () => {
        workers[i].send({'index' : i });
    });
};

// Spawn workers.
for (var i = 0; i < num_processes; i++) {
    spawn(i);
} // Code to run if we're in a worker process
} else {
var redis = require('redis');
const sio_redis = require('socket.io-redis'),

redisClient = redis.createClient();
redisClient.on('connect', function () {
    redisClient.flushdb(function (err, succeeded) {
        logger.debug("redis db cleared on startup--", succeeded); // will be true if successfull
    });
});

var RedisStore = require('connect-redis')(session);
const redisStore = new RedisStore({'host': 'localhost', 'port': 6379, 'client': redisClient});
var server = require('http').Server(app);
var listeningServer = server.listen(3002);
}

如果由于某种原因导致任何实例退出或死亡,它将清除redis

中的所有会话和数据

我不希望这种情况发生。在这种情况下我应该如何使用redis,以便清除与该实例对应的会话和数据?

2 个答案:

答案 0 :(得分:2)

您可以检查当前进程是否为主进程。这样,它只会在您第一次启动应用时刷新。如果任何fork重新启动,那么它将不会刷新db。

redisClient = redis.createClient();
redisClient.on('connect', function() {
    if (cluster.isMaster) {
        redisClient.flushdb(function(err, succeeded) {
            logger.debug("redis db cleared on startup--", succeeded); // will be true if successfull
        });
    }else{
        logger.debug("Forked instance no need to flush redis db"); // 
    }
});

答案 1 :(得分:1)

基本上有两种解决方法我认为是理智的:

  • 不要冲洗redis,
  • 从实例启动中单独刷新。

不要刷新

您说要在启动时清理会话数据。好吧,让会话不在内存中的一点是在会话中坚持他们,并保持你的实际应用服务器(Node.js应用程序)无状态。

你可以,例如在所有会话数据上设置过期密钥。所以每次你“保存”一个会话,你也会在那个会话上setex,甚至可以在你每次访问会话时延长这个TTL(所以,会话在上次触摸后12小时有效,或者其他什么)。或者,根据您的使用情况,会话中间件可以执行此操作,例如https://stackoverflow.com/a/45019589/162070

或者根本没有过期。

独立冲洗

也许您只刷新会话,因为您希望有更改,而旧会话将无效。或者有明确的要求,即在每个新的部署上,您清理会话数据。无论如何,你将其分开。例如,您的server.js作为您的应用,并且有一个单独的session-cleanup.js文件,可以连接到redis,刷新和断开连接。然后像这样设置npm:

"scripts": {
    "session.cleanup": "node lib/session-cleanup.js",
    "start": "npm run session.cleanup && node lib/server.js",
    ...
}

这样,在运行server.js并运行集群模式之前,您将首先清理会话。如果您的群集实例死亡并重生,则不会发生任何事情。

现在,每次重新部署时,都要清理它。或者甚至从“开始”中删除它,并让您的部署管道显式调用npm run session.cleanup。您甚至可以在管理UI中公开一个按钮来在运行时执行此操作(这可能会让您退出:)),重点是,会话清理现在是服务器启动时的一个单独问题。