redis 实现事件订阅和发布
redis 中实现了一种消息通信模式, 发布 pub , 订阅 sub .
这2个模式看上去是一对一握手状态,其实不然, redis 在实现 消息发布和订阅模块上做了充足的解耦.
如何理解:
redis 在消息发布的时候,并不是直接发送给所有的消息订阅者,而是发送到了一个频道上 (channel ), 这个频道再做转发,发给所有对这个频道感兴趣的人.
发布者可以同时发布多个,订阅者也可以同时订阅多个,并不是一对一的关系.
而在整个实现逻辑上和观察者模式非常相似.
消息订阅者 sub 就像 观察者.
消息发布者 pub 就像一个事件.
onmessage 处理函数就像一个事件绑定函数.
观察者细致的观察着周围事件(sub 订阅了某个频道上的消息) , 当一个事件触发时 (消息发布者 突然针对某个频道发布了一个消息 ),观察者马上观察到事件后,迅速触发事件绑定函数 ( 执行了 onmessage 方法 )
用node.js 做一个简单的实现:
订阅:
var config = require("config"); var redis = require("redis"); var client1 = redis.createClient(config.port1, config.host1); var client2 = redis.createClient(config.port2, config.host2); client1.on("message", function (channel, message) { //订阅消息被触发时的绑定函数1 }); client2.on("message", function (channel, message) { //订阅消息被触发时的绑定函数2 }); client1.subscribe("一介布衣"); //订阅 一介布衣 频道 client2.subscribe("yijiebuyi"); //订阅 yijiebuyi 频道
这个过程和 eventEmitter 类实现事件自定义函数一样,必须先有上面的观察者,否则事件触发了,结果没有人观察发现,就算有事件处理函数也不会触发,所以上面的订阅一定是在消息发布之前运行.
发布:
var config = require("config"); var redis = require("redis"); var client1 = redis.createClient(config.port1, config.host1); var client2 = redis.createClient(config.port2, config.host2); //具体的业务处理1 function A(){ //一大堆的业务处理,之后突然发布一个事件 client.publish("一介布衣", 'http://yijiebuyi.com'); } //具体业务处理2 function B(){ //一大堆的业务处理,之后突然发布另一个事件 client2.publish("yijiebuyi", '一介布衣博客'); }
这时redis 就会把消息发布到对应的频道上,然后频道广播出去,我们上面注册的2个观察者就监听到了对应频道上来了消息,同时触发事件绑定函数.
什么时候会用到:
多人聊天
邮件服务器
记录站点操作日志
站内信 等.