Nodejs 数据库 ·

nodejs使用redis发布订阅

一般来说,发布与订阅(又称为pub/sub)的特点是订阅者(listener)负责订阅频道(channel),发送者(publisher)负责向频道发送二进制字符串消息(binary string message)。每当有消息被发送至给定频道时,频道的所有订阅者都会接收到消息,我们也可以吧频道看作是电台,其中订阅者可以同时收听多个电台,而发送者则可以在任何电台发送消息。

下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系
nodejs使用redis发布订阅
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
nodejs使用redis发布订阅

redis的发布订阅命令很少,下面来看一下其命令及功效

命令 描述
PSUBSCRIBE pattern [pattern ...] 订阅一个或多个符合给定模式的频道。
PUBSUB subcommand [argument [argument ...]] 查看订阅与发布系统状态,它由数个不同格式的子命令组成。
PUBLISH channel message 将信息发送到指定的频道。
PUNSUBSCRIBE [pattern [pattern ...]] 退订所有给定模式的频道。
SUBSCRIBE channel [channel ...] 订阅给定的一个或多个频道的信息。
UNSUBSCRIBE [channel [channel ...]] 指退订给定的频道。

下面来看一下在nodejs中如何使用redis的发布订阅。
nodejs集成redis这篇文章中已经说明了如何在nodejs中集成redis,在这里我们需要对封装好的redis文件进行一些修改

//redis封装
var redis = require('redis');

var client = redis.createClient(6379,'127.0.0.1',{});
var client1 = redis.createClient(6379,'127.0.0.1',{});
client.on('error',function(err){
    console.log('Redis Error:'+err);
});
client.on('ready',function(err){
    //准备就绪后订阅chat频道
    client1.subscribe("chat");
    console.log("订阅chat成功。");
    console.log("redis is ready ok");
})
client.on('connect',function(){
    console.log('redis connect ok');
})
 //监听订阅成功事件
client1.on("subscribe", function (channel, count) {
    console.log("client subscribed to " + channel + "," + count + " total subscriptions");
});
//收到消息后执行回调,message是redis发布的消息
client1.on("message", function (channel, message) {
    console.log("我接收到信息了" + message);
});
//监听取消订阅事件
    client1.on("unsubscribe", function (channel, count) {
        console.log("client unsubscribed from" + channel + ", " + count + " total subscriptions")
    });
exports.client = client;
exports.redis = redis;

我们需要新建立一个client来进行订阅,已有的client用来进行发布,每一个事件都有相应的方法来进行接收,上面代码已经写的很明白,不在赘述。下面要说的就是进行发布了
我们还是通过路由的方式来进行示例

/*
发布订阅模式
*/
router.get("/sendSubscribe",function(req,res){
    var data = req.query.data;
    myRedis.client.publish("chat",data,function(err,result){
        console.log("订阅结果");
        console.log(result);
        if(!err){
            res.json(result)
        }else{
            res.json(err)
        }
    })
})

启动服务器后,访问该链接即可实现将data信息发布到chat频道,在上面的配置中我们通过client1.subscribe("chat")对chat进行了订阅,如果你开启了一个redis客户端的话,并且也订阅了chat频道,访问上面的链接后,你就会发现客户端打印出了发布的信息。

redis的订阅和发布有一定的缺陷,其中一点就是和redis系统的稳定性有关。对于旧版的redis来说,如果一个客户端订阅了某个或某些频道,但是他的读取消息速度却不够快的话,那么不断积压的消息就会使得redis输出缓冲区的体积变得越来越大,这可能导致redis的速度变慢,甚至崩溃。也可能导致redis被操作系统强制杀死,甚至导致操作系统本身不可用。但是也不用太担心,新版的reids不会出现这种问题,因为他会自动断开不符合client-output-buffer-limit pubsub配置选项要求的订阅客户端。

另一起缺陷就是和数据传输的可靠性有关。任何网络系统在执行操作时都可能遇上断线的情况,而断线产生的链接错误通常会使得网络链接两端中的其中一端进行重新连接。但是如果客户端在执行订阅操作的过程中断线,那么客户端将丢失在断线期间发送的所有消息,因为依靠频道来禁售消息的用户可能会对redis提供的publish命令和subscribe命令的语义感到失望。当然,如果你喜欢简单易用的publish和subscribe命令,并且能够承担可能丢失一小部分数据的防线,那么你也可以继续使用redis提供的发布与订阅。

参与评论