当前位置: 首页 > 知识库问答 >
问题:

我应该使用什么?插座io房间还是Redis酒吧?

商宏爽
2023-03-14

非常简单的问题。我正在使用nodejs作为我的后端构建一个实时游戏,我想知道是否有任何信息可以说明哪个更可靠,哪个更高效?我在整个代码中大量使用Redis和Socket.io。所以我想知道我是否应该使用Socket.io的房间,还是使用redis的pub-sub会更好?

更新:刚刚意识到,您可能希望通过套接字使用redis发布/订阅有一个非常重要的原因。io房间。带插座。io室当您向侦听器发布时,(浏览器)客户端接收消息,而使用redis,实际上是(服务器上的redis)客户端接收消息。因此,如果您想通知所有(服务器)客户端特定于每个客户端的信息,并可能在传递给浏览器客户端之前进行一些处理,那么最好使用redis。使用redis,您可以启动一个事件来生成每个用户的单独数据,就像使用socket一样。io您必须一次实际生成所有用户的唯一数据,然后循环遍历并向他们发送各自的数据,这几乎违背了房间的用途,至少对我来说是这样。

不幸的是,就我的目的而言,我现在只能使用redis。

更新2:最终开发了一个插件,仅使用2个redis连接,但仍允许单独的客户端处理,请参阅下面的答案......

共有2个答案

姜俊民
2023-03-14

最后,我编写了一个节点插件,以允许许多pub-sub客户端,但只需要2个redis连接,而不是每个socketio连接上都需要一个新的连接,它一般都可以工作,我想其他人可能会使用它。

代码假定您有套接字。io运行和设置,在本例中基本上是任意数量的套接字。io客户端可以连接,并且始终只使用2个redis连接,但所有客户端都可以订阅自己的频道。在本例中,所有客户端都会收到一条消息“sweet message!”10秒后。

socket.io示例(利用redis pub-sub):

var
    RPubSubFactory = require('rpss.js');

var 
    redOne = redis.createClient(port, host),
    redTwo = redis.createClient(port, host);

var pSCFactory = new RPubSubFactory(redOne);

io.sockets.on('connection', function(socket){
    var cps = pSCFactory.createClient();
    cps.onMessage(function(channel, message){
        socket.emit('message', message);
    });
    io.sockets.on('disconnect', function(socket){
        // Dont actually need to unsub, because end() will cleanup all subs, 
        // but if you need to sometime during the connection lifetime, you can.
        cps.unsubscribe('cool_channel');
        cps.end();
    });
    cps.subscribe('cool_channel')
});

setTimeout(function(){
    redTwo.publish('cool_channel', 'sweet message!');
},10000);

实际插件代码:

var RPubSubFactory = function(){

    var 
        len,indx,tarr;
    var
        dbcom = false,
        rPubSubIdCounter = 1,
        clientLookup = {},
        globalSubscriptions = {};

    // public
    this.createClient = function()
    {
        return new RPubSupClient();
    }

    // private
    var constructor = function(tdbcom)
    {
        dbcom = tdbcom;
        dbcom.on("message", incommingMessage);
    }
    var incommingMessage = function(rawchannel, strMessage)
    {
        len = globalSubscriptions[rawchannel].length;
        for(var i=0;i<len;i++){
            //console.log(globalSubscriptions[rawchannel][i]+' incomming on channel '+rawchannel);
            clientLookup[globalSubscriptions[rawchannel][i]]._incommingMessage(rawchannel, strMessage);
        }
    }

    // class
    var RPubSupClient = function()
    {
        var 
            id = -1,
            localSubscriptions = [];

        this.id = -1;
        this._incommingMessage = function(){};

        this.subscribe = function(channel)
        {
            //console.log('client '+id+' subscribing to '+channel);
            if(!(channel in globalSubscriptions)){
                globalSubscriptions[channel] = [id];
                dbcom.subscribe(channel);
            }
            else if(globalSubscriptions[channel].indexOf(id) == -1){
                globalSubscriptions[channel].push(id);
            }
            if(localSubscriptions.indexOf(channel) == -1){
                localSubscriptions.push(channel);
            }
        }
        this.unsubscribe = function(channel)
        {
            //console.log('client '+id+' unsubscribing to '+channel);
            if(channel in globalSubscriptions)
            {
                indx = globalSubscriptions[channel].indexOf(id);
                if(indx != -1){
                    globalSubscriptions[channel].splice(indx, 1);
                    if(globalSubscriptions[channel].length == 0){
                        delete globalSubscriptions[channel];
                        dbcom.unsubscribe(channel);
                    }
                }
            }
            indx = localSubscriptions.indexOf(channel);
            if(indx != -1){
                localSubscriptions.splice(indx, 1);
            }
        }
        this.onMessage = function(msgFn)
        {
            this._incommingMessage = msgFn;
        }
        this.end = function()
        {
            //console.log('end client id = '+id+' closing subscriptions='+localSubscriptions.join(','));
            tarr = localSubscriptions.slice(0);
            len = tarr.length;
            for(var i=0;i<len;i++){
                this.unsubscribe(tarr[i]);
            }
            localSubscriptions = [];
            delete clientLookup[id];
        }        
        var constructor = function(){
            this.id = id = rPubSubIdCounter++;
            clientLookup[id] = this;
            //console.log('new client id = '+id);
        }        
        constructor.apply(this, arguments);
    }    
    constructor.apply(this, arguments);
};

module.exports = RPubSubFactory;

我胡思乱想,尽量提高效率,但在做了一些不同的速度测试后,我得出结论,这是我能达到的最快速度。

对于最新版本:https://github.com/Jezternz/node-redis-pubsub

刘意
2023-03-14

Redis pub/sub非常适合所有客户端都可以直接访问redis。如果您有多个节点服务器,一个可以将消息推送给其他节点服务器。

但是,如果浏览器中也有客户端,则需要其他东西将数据从服务器推送到客户端,在本例中是socket。io很棒。

现在,如果您将socket.io与Redis存储一起使用,socket.io将使用Redis pub/sub在服务器之间传播消息,服务器将将消息传播到客户端。

所以使用套接字。io室带插座。使用Redis store配置的io可能是最简单的。

 类似资料:
  • 问题内容: 很简单的问题。我正在使用nodejs作为后端构建实时游戏,我想知道是否有任何信息可用于确定哪个更可靠,哪个更有效?我在整个代码中都大量使用Redis和Socket.io。所以我想知道我是否应该使用Socket.io的房间,还是最好使用redis的pub- sub ? 更新: 刚意识到有一个非常重要的原因,为什么您可能想在socket.io房间中使用redis pub / sub。使用S

  • 我正在研究Nodejs/socket.io实时聊天,我需要一些实现房间的建议。 哪一个更好,使用名称空间还是使用房间特性来完全隔离彼此之间的聊天? 是否存在资源使用差异?

  • 从外观上看-似乎创建了一个对象的克隆。如果是这样,那么对于实现可克隆接口(只有不可变对象是新的,因为可变对象有引用复制)的关注,哪一个是最好的,为什么? 我昨天实现了克隆,然后意识到我必须为非字符串/首字母元素提供自己的修改。然后我被告知我现在正在使用的。这两个实现似乎都提供了类似的功能。 谢谢

  • 我正在设计一个数据库,该数据库将在Android using Room中实现,在阅读文档后,我发现没有关于使用Int或Long作为主键的建议。 在某些地方,它们使用int主键定义实体: 但是在其他地方,它说如果你想得到插入的最后一行的ID,“插入”方法返回一个长的。 如果@插入方法只接收到1个参数,它可以返回一个long,这是插入项的新rowId。如果参数是数组或集合,则应返回long[]或Lis

  • 问题内容: 通过它的外观- 似乎创建了一个对象的克隆。如果是这样的话,那么与实现Cloneable接口有关的担忧(只有不可变对象才是新对象,因为可变对象复制了引用)是最好的,为什么? 昨天我实现了cloneable,然后意识到我必须对非 String / Primative 元素提供自己的修改。然后,我被告知我正在使用哪个。两种实现似乎都提供了类似的功能。 谢谢 问题答案: Josh Bloch提

  • 问题内容: 我正在使用c / c 为osx和linux开发命令行界面可执行文件。该项目将链接到opencv。我应该使用libc 还是libstdc ++? 问题答案: 我会为每个操作系统使用本机库,即GNU / Linux上的libstdc 和Mac OS X上的libc 。 libc 在GNU / Linux上不是100%完整的,而libstdc 更完整时使用libc并没有真正的优势。另外,如果