Python-redis生产者消费者模式和发布者订阅者模式

Python-redis生产者消费者模式和发布者订阅者模式

生产者消费者模式

生产者消费者模式是一个或多个消费者监听redis消息队列,一旦生产者有消息发出,那么消费者谁抢到算谁的,消息队列没有消息后,则继续监听等待。
示例代码:
关键方法:blpop

import redis

# 生产者消费者模式
class RedisTask(object):
    def __init__(self,info):
        self.rcon = redis.StrictRedis(host='localhost', db=1)
        self.queue = info


    def listen_task(self):
        while True:
            task = self.rcon.blpop(self.queue, 0)    # 填0为阻塞等待,填大于0的数字为超时等待,超过时间没有消息接收到,则task为None
            print(task)
if __name__ == '__main__':
    info = 'abc'
    redis_task = RedisTask(info)
    redis_task .listen_task()

发布者订阅者模式

发布者订阅者模式是一个或多个客户端订阅消息频道,只要发布者发布这个频道的消息,则所有订阅者都可以接收到此频道的消息,等待模式为阻塞等待。
示例代码:
关键方法:pubsub,publish,subscribe,psubscribe

发布者

import redis

# 发布者
redis_conn = redis.StrictRedis(host='localhost', db=5)
redis_conn.publish('test1', 'abcdef')

订阅者

#订阅者
redis_conn = redis.StrictRedis(host='localhost', db=5)
rc_sub = redis_conn.pubsub()
rc_sub.subscribe('test1')
# 订阅多个频道使用psubscribe方法,参数为列表
# rc_sub.psubscribe(['test1','test2','test3'])
for item in rc_sub.listen():
    if item['type'] == 'message':
        print(item['channel'])
        print(item['data'])
<think>我们正在讨论发布-订阅模式生产者-消费者模式的区别联系。根据引用[1][3],我们可以总结如下: **生产者-消费者模式(Producer-Consumer)**: - 生产者数据推送到一个共享的缓冲区(或消息队列),消费者从该缓冲区中取出数据进行处理。 - 关键点是所有消费者都从同一个缓冲区中消费数据,因此每个消费者都会看到相同的数据流(引用[3])。 - 通常用于解耦生产者消费者,平衡生产速度消费速度的差异(引用[2])。 **发布-订阅模式(Publish-Subscribe)**: - 发布者将消息发送到一个中间代理(通常称为消息中心或主题),订阅者首先向中间代理注册自己感兴趣的主题。 -发布者发布消息到某个主题时,中间代理会将消息推送给所有订阅了该主题的订阅者- 每个订阅者只接收自己订阅的主题的消息,因此不同的订阅者可能看到不同的数据流(引用[3])。 **区别**: 1. **消息传递方式**: - 生产者-消费者:所有消费者共享同一个队列,每条消息只能被一个消费者消费(点对点)。 - 发布-订阅:每个订阅者都有自己的订阅主题,一条消息可以被多个订阅者同时接收(广播)。 2. **数据流**: - 生产者-消费者:所有消费者获取相同的数据(如果多个消费者消费同一个队列,则每条消息只能被一个消费者消费,但整个数据流是相同的)。 - 发布-订阅:订阅者只接收自己感兴趣的数据。 3. **中间代理的角色**: - 生产者-消费者:中间代理(队列)主要作为缓冲区,不负责消息的路由。 - 发布-订阅:中间代理(消息中心)负责根据主题将消息路由到相应的订阅者。 **联系**: - 发布-订阅模式可以看作是生产者-消费者模式的一种扩展(引用[3])。在发布-订阅模式中,发布者相当于生产者订阅者相当于消费者,但中间增加了消息路由的功能。 - 两种模式都用于解耦消息的发送者接收者。 **应用场景**: - **生产者-消费者模式**:适用于任务分发、负载均衡等场景。例如,多个工人从同一个任务队列中获取任务进行处理(引用[2])。 - **发布-订阅模式**:适用于事件驱动的系统,如实时通知、日志收集等。例如,在股票交易系统中,多个订阅者订阅不同股票的价格更新(引用[3])。 **示例**: - Kafka支持两种模式(引用[3]): - 生产者-消费者模式:同一个消费者组内的消费者共同消费同一个topic的消息,每条消息只能被组内的一个消费者消费。 - 发布-订阅模式:不同的消费者组可以独立订阅同一个topic,每个组都会收到全部消息。 **Guava中的发布-订阅模式**(引用[4]): - Guava提供了EventBus来实现发布-订阅模式,它允许组件之间通过事件进行通信。发布者发布事件,订阅者通过注解方法注册事件处理函数。 总结:两种模式都是解耦的经典模式,但适用场景不同。生产者-消费者模式更关注于任务的分发负载均衡,而发布-订阅模式更关注于消息的广播按主题分发。</think>### 发布-订阅模式生产者-消费者模式的区别与联系 #### 核心区别 | 维度 | 生产者-消费者模式 | 发布-订阅模式 | |------------------|--------------------------------------|----------------------------------------| | **消息传递方式** | 点对点(队列) | 广播(主题/频道) | | **消息接收者** | 所有消费者获取相同数据[^3] | 订阅者只收到感兴趣的数据[^3] | | **耦合关系** | 生产者不感知消费者存在 | 发布者不感知订阅者,但需定义主题 | | **消息生命周期** | 消息被消费后即消失 | 消息可被多个订阅者重复接收 | | **典型实现** | 阻塞队列(Java BlockingQueue)[^2] | 消息代理(Kafka Topic, Redis Pub/Sub) | #### 本质联系 1. **同属解耦模式** 两者都通过中间件实现生产方与消费方的解耦[^3],解决系统组件间直接依赖问题。 2. **演化关系** 发布-订阅是生产者-消费者模式的扩展: ```mermaid graph LR A[生产者-消费者] -->|增加消息路由| B[发布-订阅] ``` 3. **混合使用场景** 现代消息系统(如Kafka)同时支持两种模式[^3]: - 同一消费者组内:生产者-消费者模式 - 不同消费者组间:发布-订阅模式 #### 应用场景对比 **生产者-消费者适用场景**: - 订单处理系统(多个处理节点消费相同订单流) - 日志批量处理(多个worker消费日志队列- 资源池管理(线程池任务分配) **发布-订阅适用场景**: - 实时事件通知(股票价格更新[^3]) - 微服务间通信(服务状态变更广播) - 用户行为追踪(不同系统订阅特定事件) - 配置中心更新(配置变更推送) #### 实现示例对比 **生产者-消费者Python队列)**: ```python from queue import Queue from threading import Thread def producer(q): while True: data = generate_data() q.put(data) # 所有消费者收到相同data def consumer(q): while True: data = q.get() # 所有消费者竞争获取相同数据 process(data) queue = Queue() Thread(target=producer, args=(queue,)).start() Thread(target=consumer, args=(queue,)).start() ``` **发布-订阅(Redis Pub/Sub)**: ```python import redis # 发布者 r = redis.Redis() r.publish('stock_IBM', 185.3) # 发布到特定频道 # 订阅者1(只收IBM数据) pubsub = r.pubsub() pubsub.subscribe('stock_IBM') # 明确订阅频道 # 订阅者2(只收TSLA数据) pubsub.subscribe('stock_TSLA') # 不同订阅者接收不同数据集 ``` #### 模式选择决策树 ```mermaid graph TD A[需要消息广播?] -->|是| B[发布-订阅] A -->|否| C{所有消费者需相同数据?} C -->|是| D[生产者-消费者] C -->|否| B ``` > **设计原则**: > - 需要严格顺序处理 → 生产者-消费者[^2] > - 需要动态增加接收方 → 发布-订阅[^4] > - 需要历史消息重放 → 发布-订阅(如Kafka)[^3] #### Guava的发布订阅实现[^4] ```java // 创建事件总线 EventBus bus = new EventBus(); // 注册订阅者(通过@Subscribe注解) class StockSubscriber { @Subscribe public void handleIBM(StockEvent event) { if(event.symbol.equals("IBM")) process(event); } } bus.register(new StockSubscriber()); // 发布事件 bus.post(new StockEvent("IBM", 185.3)); // 仅触发对IBM感兴趣的处理 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值