【问题标题】:Redis and Node.js and Socket.io QuestionsRedis 和 Node.js 和 Socket.io 问题
【发布时间】:2012-01-20 19:36:34
【问题描述】:

我一直在学习redis和node.js 有两个问题我找不到满意的答案。

我的第一个问题是关于在 node.js 中重用 redis 客户端。我找到了这个问题和答案:How to reuse redis connection in socket.io?,但它并没有让我足够满意。

现在,如果我在连接事件中创建 redis 客户端,它将为每个连接生成。所以,如果我有 20k 并发用户,就会有 20k redis 客户端。

如果我把它放在连接事件之外,它只会产生一次。

答案是他在连接事件之外为每个函数创建三个客户端。

但是,根据我对 MySQL 的了解,在编写生成子进程并并行运行的应用程序时,您需要在创建子实例的函数中创建 MySQL 客户端。如果您在它之外创建它,MySQL 将给出“MySQL 服务器已消失”的错误,因为子进程将尝试使用相同的连接。它应该为每个子进程单独创建。

所以,即使你为每个函数创建三个不同的 redis 客户端,如果你有 30k 个并发用户并发发送 2k 条消息,你应该会遇到同样的问题,对吧?因此,每个“用户”都应该在连接事件中拥有自己的 redis 客户端。我对吗?如果不是,node.js 或 redis 如何处理并发请求,与 MySQL 不同?如果它有自己的机制并在redis客户端中创建类似子进程的东西,那为什么我们需要创建三个不同的redis客户端呢?一个就够了。

我希望问题很清楚。

-- 更新--

我找到了以下问题的答案。 http://howtonode.org/control-flow 无需回答,但我的第一个问题仍然有效。

-- 更新--

我的第二个问题是这个。我也不擅长 JS 和 Node.js。所以,据我所知,如果你需要等待一个事件,你需要将第二个函数封装在第一个函数中。 (我还不知道术语)。让我举个例子;

socket.on('startGame', function() {
    getUser();
    socket.get('game', function (gameErr, gameId) {
        socket.get('channel', function (channelErr, channel) {
            console.log(user);
            client.get('games:' + channel + '::' + gameId + ':owner', function (err, owner) { //games:channel.32:game.14
                if(owner === user.uid) {
   //do something
                }
            });
        }
    });
});

所以,如果我学习正确,如果我需要等待 I/O 应答,我需要运行函数中的每个函数。否则,node.js 的非阻塞机制将允许第一个函数运行,这种情况下它会并行获取结果,但第二个函数如果需要时间获取,则可能没有结果。因此,例如,如果您从 redis 获取结果,并且您将在第二个函数中使用结果,则必须将其封装在 redis get 函数中。否则第二个函数将运行而没有得到结果。

所以,在这种情况下,如果我需要运行 7 个不同的函数并且 8. 函数需要所有这些函数的结果,我是否需要像这样递归地编写它们?还是我错过了什么。

我希望这也很清楚。

非常感谢,

【问题讨论】:

  • 顺便说一句,要完成您对第二个问题的回答,您还可以查看流控制库“async”和“step”。

标签: node.js redis


【解决方案1】:

因此,每个“用户”都应该在连接事件中拥有自己的 redis 客户端。 我说的对吗?

其实你不是:)

问题是 node.js 与 PHP 非常不同。 node.js 不会在新连接上生成子进程,这是它可以轻松处理大量并发连接的主要原因之一,包括长期连接(Comet、Websockets 等)。 node.js 使用单个进程中的事件队列按顺序处理事件。如果您想使用多个进程来利用多核服务器或多台服务器,则必须手动执行(不过,如何执行此操作超出了此问题的范围)。

因此,使用单个 Redis(或 MySQL)连接来服务大量客户端是一种完全有效的策略。这避免了为每个客户端请求实例化和终止数据库连接的开销。

【讨论】:

    【解决方案2】:

    因此,每个“用户”都应该在 连接事件。我说的对吗?

    您不应该为每个连接的用户创建一个新的 Redis 客户端,这不是正确的做法。而是最多创建 2-3 个客户端并使用它们。

    欲了解更多信息,请查看此问题:

    How to reuse redis connection in socket.io?

    【讨论】:

      【解决方案3】:

      关于第一个问题: “正确答案”可能会让你认为你擅长一个连接。 实际上,每当您在等待 IO、计时器等时,您实际上是在让节点运行队列中的等待方法。因此,如果您只使用 1 个单一连接,您实际上会将您处理的线程(单个 CPU)的性能限制为 redis 的速度——这可能是每秒数百个回调(非 redis 等待回调将仍然继续) - 虽然这不是糟糕的表现,但没有理由创造这种限制。建议创建几个(5-10)个连接来避免这个问题。对于较慢的数据库,这个数字会上升,例如MySQL,但取决于查询类型和代码细节。

      请注意,您应该根据您拥有的 CPU 数量在您的服务器上运行一些工作程序,以获得最佳性能。 关于第二个问题: 这是一种更好的做法,一个接一个地命名函数,并在代码中使用名称,而不是在你去的时候定义它。在某些情况下,它会减少内存消耗。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-08
        • 2011-10-22
        • 2014-12-23
        • 2014-03-13
        • 2016-05-15
        • 2012-11-06
        • 2012-06-19
        • 2011-03-27
        相关资源
        最近更新 更多