【问题标题】:How to design redis pub/sub for an instant messaging system?如何为即时消息系统设计 redis pub/sub?
【发布时间】:2012-04-25 21:37:42
【问题描述】:

我是 redis pub/sub 的新手。我在系统中有一个聊天工具,就像 IM。所以我想使用redis pub/sub。正如我检查过的样本,它们中的大多数都是基于聊天室设计的。在我的系统中,我将在用户之间有多个聊天室,例如;

A:B
A:C
D:C
E:F

所以,上面的线条是房间。我已经用 node.js 实现了服务器,如下所示;

var store = redis.createClient();
var pub = redis.createClient();
io.sockets.on('connection', function (socket) {
    var sub = redis.createClient();

    sub.on("message", function(pattern, data){
            data = JSON.parse(data);
        socket.send(JSON.stringify({ type: "chat", key: pattern, nick: data.nickname, message: data.text }))
        }
    });

    socket.on('message', function (messageData) {
        store.incr("messageNextId", function(e, messageId) {
        var room = ""
        var from = messageData.clientId > socket.nickname ? socket.nickname : messageData.clientId;
        var to = messageData.clientId < socket.nickname ? socket.nickname : messageData.clientId;   
            room = from + ":" + to;

        var message = { id: messageId, nickname: socket.nickname, text: messageData.text };
        store.rpush("rooms:" + room, JSON.stringify(message), function(e, r) {  
             pub.publish(room, JSON.stringify(message))
        });
    });
});

如您所见,我正在为每个连接创建一个新的 redis 订阅者。在其他聊天室示例中,redis 订阅者客户端是全局创建的。并且始终只存在三个连接,这解决了他们的问题,因为当发布者发布消息时,所有连接的客户端都应该得到它。但我在这里有一个限制。我想在两个用户之间打开一个聊天会话,只有这些用户应该是订阅者。上面的代码可以按照我的意愿工作,但我不知道redis是否可以为每个连接创建一个新的订阅者客户端。

很高兴听到您的建议。提前致谢。

【问题讨论】:

    标签: node.js redis publish-subscribe


    【解决方案1】:

    与往常一样,您需要针对自己的用例对此类事物进行基准测试——不可能给出一般性建议。您可能需要增加系统上打开文件的最大数量,无论是系统范围还是 redis 用户。当然,这也适用于运行您的 Web 服务器的用户。

    也就是说,当用户离开时,您应该确保收听 redis 订阅者的 socket.on('disconnect')quit()。您可能还想知道 socket.io 有一个 redis 后端,它利用了 redis pub/sub,它也有房间的概念,所以使用它可能会为自己省点麻烦,因为您已经依赖于 socket .io.

    编辑:快速检查后,我在 991 个订阅者之后从 Redis 收到此错误消息:

    Ready check failed: Error: Error: ERR max number of clients reached
    

    这里是默认的redis.conf

    # Set the max number of connected clients at the same time. By default
    # this limit is set to 10000 clients, however if the Redis server is not
    # able ot configure the process file limit to allow for the specified limit
    # the max number of allowed clients is set to the current file limit
    # minus 32 (as Redis reserves a few file descriptors for internal uses).
    #
    # Once the limit is reached Redis will close all the new connections sending
    # an error 'max number of clients reached'.
    #
    # maxclients 10000
    

    我的系统 (Ubuntu 11.11) 的默认 nofile 限制为 1024,因此我的快速测试应该在 992 个连接的客户端后失败,这似乎与测试差不多(我也有一个发布者客户端)。我对您的建议是检查您的 nofile 限制(在我的系统上,它位于 /etc/security/limits.{conf,d/*} 和您的 redis maxclients 设置中,然后进行基准测试、基准测试、基准测试!

    【讨论】:

    • 感谢您的详细回答。我知道 socket.io 有房间的概念,但我不知道它在幕后使用 pub/sub。我会尝试一下。当然,我将开始基准测试,目前我只是想找到一个好的起点。感谢您的建议。
    • @AliErsöz:太好了。如果您发现我的回答令人满意,请考虑点击左上角的大勾号将其作为正确答案。
    猜你喜欢
    • 1970-01-01
    • 2017-09-25
    • 1970-01-01
    • 2019-02-09
    • 1970-01-01
    • 2013-07-28
    • 2014-02-07
    • 2014-09-25
    • 1970-01-01
    相关资源
    最近更新 更多