深入Redis之 Publish/Subscribe 消息发布订阅 (四)-张柏沛IT博客

正文内容

深入Redis之 Publish/Subscribe 消息发布订阅 (四)

栏目:Linux 发布时间:2020-02-23 15:04 浏览量:243

发布订阅


角色: 发布者  订阅者  频道

发布订阅的通信模型:

发布订阅模型


发布者和订阅者都在客户端,而频道在redis服务端。
发布者发布消息到redis服务器,频道会将消息广播到关注了这个频道的所有订阅者。

命令 
publish channel message     # 发布消息,返回订阅者个数
subscribe channel   # 订阅,可以接多个channel
unsubscribe channel     # 取消订阅,可以接多个channel


对比消息队列和发布订阅:
二者的共同点是:消息发布者和订阅者都在客户端,频道或者队列在服务端。
不同点:发布订阅会将消息发给所有订阅者,但是消息队列则只有一个订阅者能接收到(或者说是抢到)队列弹出来的元素。

 

消息队列模型

 

所以消息队列除了能用来缓解请求压力之外,还能够实现一个"抢"的功能,例如实现抢红包功能。不过消息队列用来处理并发请求用的是阻塞的brpop命令,而实现抢红包应该是列表中已经有红包,直接使用rpop就好。

注意,订阅者只可以接收到订阅之后的消息,订阅之前频道发的消息是接收不到的。


Python演示:
订阅者 subscriber.py

# coding=utf-8

import redis
import time

r = redis.Redis("127.0.0.1",6379)
p = r.pubsub()  # 创建一个PubSub 发布订阅对象

p.subscribe("test_channel")   # 订阅一个频道

while True:
    # 接收消息
    data = p.get_message()
    if data:
        print(data)
    time.sleep(0.1)


# 或者使用p.listen(),listen()会返回一个生成器,可以遍历这个生成器来获取消息,当频道没有消息的时候,listen会阻塞循环;当有消息时,会接收消息
#for message in p.listen():
#    print(message)


    
发布者 publisher.py

# coding=utf-8

import redis

r = redis.Redis("127.0.0.1",6379)
res = r.publish("test_channel","This is test data");

print(res)


订阅者先订阅
python subscriber.py 

发布者再发布
python publisher.py

 

注意:当客户端订阅了一个频道,这个客户端脚本就会一直处于一个阻塞的运行状态。如果想要结束脚本就要调用 unsubscribe 取消订阅
 

# coding=utf-8

import redis
import time

r = redis.Redis("127.0.0.1",7000)
p = r.pubsub()  # 创建一个PubSub 发布订阅对象

p.subscribe("test_channel")   # 订阅一个频道

count = 0
for message in p.listen():
    count+=1
    print(message)
    if count>5:
        p.unsubscribe("test_channel")

 

如果是用php来订阅消息,取消订阅后脚本还无法结束运行,此时要die强行终止才行:

<?php 
    set_time_limit(0);
    $r = new Redis();
    $r->connect("127.0.0.1",7000);
    $r->subscribe(['test'],"cb");
    function cb($redis,$channel,$msg){
        var_dump($msg);
        $redis->unsubscribe(["test"]);
        die;
    }
?>

 

如果您需要转载,可以点击下方按钮可以进行复制粘贴;本站博客文章为原创,请转载时注明以下信息

张柏沛IT技术博客 > 深入Redis之 Publish/Subscribe 消息发布订阅 (四)

热门推荐
推荐新闻