RabbitMQ基础知识

我们可以把 RabbitMQ 的运作看作是一个极其智能的物流分拣中心

1. 核心四大角色 🏗️

  • 生产者 (Producer) 🏭:消息的发送方。它只负责把消息发给交换机,并贴上一个"路由标签"(Routing Key)。

  • 交换机 (Exchange) 🚦:分拣中心的核心。它接收生产者的消息,并根据规则决定分发到哪个仓库(队列)。

  • 队列 (Queue) 📥:消息的缓冲区。消息在这里排队,直到被消费者取走。一个队列可以存放成千上万条消息。

  • 消费者 (Consumer) 👤:消息的接收方。它连接到队列,取走消息并执行具体的业务逻辑。

基础:简单的"生产者"与"消费者" 📮

这是最基础的模式:生产者将消息发送到队列,消费者从中取出。

生产者 (send.py):

复制代码
import pika

# 1. 建立连接
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

# 2. 声明队列(确保队列存在)
channel.queue_declare(queue='hello')

# 3. 发送消息
# exchange='' 表示使用默认交换机,它会将消息直接路由到 routing_key 指定的队列
channel.basic_publish(exchange='',
                      routing_key='hello',
                      body='Hello RabbitMQ!')

print(" [x] 已发送 'Hello RabbitMQ!'")
connection.close()

消费者 (receive.py):

复制代码
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()

# 声明队列(防止消费者先启动导致找不到队列)
channel.queue_declare(queue='hello')

# 定义回调函数:当收到消息时执行的操作
def callback(ch, method, properties, body):
    print(f" [x] 收到消息: {body.decode()}")

# 告诉 RabbitMQ 使用 callback 来接收消息
channel.basic_consume(queue='hello', on_message_callback=callback, auto_ack=True)

print(' [*] 等待消息中... 按 CTRL+C 退出')
channel.start_consuming()

2. 它们是如何关联的?(Binding & Routing Key) 🔗

要让交换机知道把消息发给哪个队列,需要两个关键设置:

  • 绑定 (Binding):这是交换机和队列之间的"连接关系"。你可以理解为队列向交换机"订阅"了某种类型的消息。

  • 路由键 (Routing Key):生产者发消息时带上的"标签"。交换机会对比消息的标签和绑定的规则,匹配上了才投递。


3. 四大交换机模式(决定如何投递) 🛣️

这是 RabbitMQ 最灵活的地方,决定了消息的流向:

  1. Direct (直连模式) 🎯:精确匹配。路由键必须完全一致。例如:消息标签是 error,只有绑定了 error 的队列能收到。

  2. Fanout (广播模式) 📢:无视标签。交换机会把消息复制一份,发给所有绑定到它的队列。适合下单后同时通知库存、短信、积分系统。

  3. Topic (主题模式) 📝:模糊匹配。支持通配符(如 *.orange.*user.#)。适合按类别订阅消息,比如"所有关于用户的日志"。

  4. Headers (头模式) 🗄️:不根据标签,而是根据消息头里的属性进行匹配(较少使用)。

进阶:使用交换机 (Exchange) 实现广播模式 📢

在"广播模式"(Fanout)下,生产者不把消息发给特定队列,而是发给交换机,由交换机发给所有绑定的队列。

生产者 (emit_log.py):

Python

复制代码
# ... 建立连接代码同上 ...
# 声明一个名为 'logs' 的 fanout 交换机
channel.exchange_declare(exchange='logs', exchange_type='fanout')

channel.basic_publish(exchange='logs',
                      routing_key='',  # 广播模式下不需要指定具体队列名
                      body='系统日志:这是一条广播消息')

消费者 (receive_logs.py):

复制代码
# ... 建立连接和声明交换机代码同上 ...
# 1. 创建一个随机命名的临时队列,消费者断开后自动删除
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue

# 2. 将队列绑定到交换机上(这就是"订阅")
channel.queue_bind(exchange='logs', queue=queue_name)

# ... 之后的部分同基础消费者 ...

精准打击:主题模式 (Topic) 🧩

主题模式允许我们使用通配符(如 * 匹配一个单词,# 匹配多个单词)进行灵活路由。

生产者:

复制代码
# 声明 topic 类型的交换机
channel.exchange_declare(exchange='topic_logs', exchange_type='topic')

# 发送一条带标签的消息
routing_key = 'usd.stock.nyse' 
channel.basic_publish(exchange='topic_logs', routing_key=routing_key, body='美股数据更新')

消费者(只订阅股票数据):

复制代码
# 绑定键使用通配符:匹配所有以 .stock. 结尾的中间部分
channel.queue_bind(exchange='topic_logs', queue=queue_name, routing_key='*.stock.#')

4. 核心优势:为什么要用它? 🛡️

  • 异步处理 (Asynchrony) ⏳:用户注册后,主程序直接返回成功,发邮件等耗时操作交给 RabbitMQ 慢慢处理,极大提升用户体验。

  • 应用解耦 (Decoupling) 🧱:订单系统不需要知道库存系统长什么样,只要把消息发给 RabbitMQ,库存系统自己去领任务即可。

  • 削峰填谷 (Peak Shaving) 🌊:秒杀活动流量暴增时,消息先堆积在队列里,后端服务器按自己的节奏慢慢处理,防止系统被瞬间冲垮。


5. 消息的安全性(不丢失的保障) 🔒

  • 持久化 (Persistence):把消息存入硬盘,即使 RabbitMQ 重启,消息也不会丢失。

  • 确认机制 (Ack) :消费者处理完消息后回复一个 ACK。如果消费者在处理时挂了,没有回复,RabbitMQ 会把这条消息重新发给别人,确保一定被处理。


相关推荐
倒霉熊dd24 分钟前
Python学习(第一部分 语法与数据结构/核心基础)
大数据·python·学习·pip
仅此,41 分钟前
deep agent整合 DeepSeek 记录
python·langchain·agent·deep agent sdk
ftpeak1 小时前
AI开发之LangGraph教程6~自定义状态 (Custom State)
python·ai·langchain·langgraph
m0_738120721 小时前
渗透测试——Djinn1靶场详细渗透提权过程讲解(绕过黑名单限制,命令执行反弹shell,pyc反编译,代码白盒分析,python沙盒逃逸)
开发语言·python·php
Ares-Wang2 小时前
AI》》欧氏距离、曼哈顿距离 切比雪夫距离 等
人工智能·python
陈eaten2 小时前
windows上协调多版本python以及虚拟环境
开发语言·windows·python·pycharm·pip·虚拟环境·py
一晌小贪欢2 小时前
告别 `datetime` 混乱:使用 Python 类型注解构建健壮的时间处理管道
开发语言·python·时间·时间类型·时间模块
嘛?2507012 小时前
Python高阶基础
python
li星野2 小时前
哈希表通关八题:从两数之和到LRU缓存,手撕高频面试题(Python + C++)
python·缓存·散列表
yaoxin5211232 小时前
401. Java 文件操作基础 - 使用 Buffered Stream I/O 写入文本文件
java·开发语言·python