【问题标题】:How to use redis with node js clusters如何在 node js 集群中使用 redis
【发布时间】:2018-03-15 17:26:30
【问题描述】:

我一直使用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);
}

如果任何实例由于某种原因exit or die,它将清除redis中的所有会话和数据

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

【问题讨论】:

  • 您将如何运行实例?
  • 我已经添加了代码,实例是如何运行的

标签: node.js redis


【解决方案1】:

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

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

【讨论】:

  • 你能告诉我什么时候应该使用redis集群吗?
  • Redis 集群通常用于需要横向扩展的情况。我不能真正回答你的问题,你必须做一些研究和学习。
【解决方案2】:

我认为基本上有两种方法可以解决这个问题:

  • 不要刷新 redis,
  • 将刷新与实例启动分开。

不要冲洗

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

你可以,例如在所有会话数据上设置过期键。所以每次你“保存”一个会话时,你也会在那个会话上设置ex,甚至可以选择在每次访问会话时延长这个 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 中公开一个按钮以在运行时执行此操作(这可能会使您注销 :)),关键是,会话清理现在与服务器启动是一个单独的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-28
    • 2020-01-29
    • 1970-01-01
    • 1970-01-01
    • 2018-03-09
    • 1970-01-01
    • 2022-06-13
    • 1970-01-01
    相关资源
    最近更新 更多