RabiitMq
生产者消费模型
消息队列 存储生产者发送的消息 直到消费者来消费(队列可持久化和多质量服务(qos0,1,2))
将消息发送到队列的角色成为生产者
从队列中取出消息的称之为消费者(消费者可以是一个 可以是多个)
通知机制:消费者会每隔一段时间像消息队列询问是否有新消息。轮询
生产者主动发给消费者称为推送
确认机制:消费者确认消息要发送一条消息给队列(不然队列会重发或发给其它消费者)
经过拒绝的消息将会被放到死信队列中。
---
交换机类型:
直连交换机
扇出交换机
主题交换机
头部交换机
Direct Exchange:直联交换机,基于Routing Key精确匹配。
Fanout Exchange:扇出交换机,广播所有消息给绑定的所有队列。
Topic Exchange:主题交换机,基于通配符模式匹配Routing Key。
Headers Exchange:头部交换机,根据消息的header属性进行匹配
--
消息丢失解决:从生产者到消息队列丢失
生产者 开事务 发送有异常就会回滚 tranciation
第二种 cofirm 开启后 信道上的所有消息都会被指派唯一id
当所有都到达后 会发送一个ack请求告诉生产者到了
从消息队列到消费者丢失
消息队列丢数据 开启持久化磁盘的配置
1、将queue的持久化标识durable设置为true,则代表是一个持久的队列
2、发送消息的时候将deliveryMode=2
---
消费者丢数据
消费者将自动确认模式改为手动确认ack。
到底ack是一一条条确认id 还是一个确认id表示所有的都到了
在RabbitMQ的发布确认机制中,basic.ack(确认)可以是一条条单独的消息确认,也可以是一个确认表示多个消息都已经被成功处理。这取决于生产者如何设置和处理确认。
单个消息确认
默认情况下,每个basic.ack或basic.nack都是针对单个消息的确认。每个消息有一个唯一的deliveryTag,当Broker发送一个确认时,它会包含这个deliveryTag,表明该特定的消息已经被成功处理或未能被处理。
批量确认
RabbitMQ还支持批量确认,这意味着一个确认可以表示多个消息都被成功处理了。这是通过设置multiple标志来实现的:
multiple=False:默认值,表示仅确认特定的deliveryTag对应的消息。
multiple=True:表示确认所有小于等于该deliveryTag的未确认消息。
示例
假设生产者发送了以下消息,并且它们的deliveryTag依次为1, 2, 3, 4, 5:
如果Broker发送了一个basic.ack,其中deliveryTag=3且multiple=False,那么只有deliveryTag=3的消息被确认。
如果Broker发送了一个basic.ack,其中deliveryTag=3且multiple=True,那么deliveryTag=1, 2, 3的所有消息都被确认。
实际应用
在实际应用中,生产者通常会维护一个未确认消息的列表,并在接收到确认后更新这个列表。如果使用批量确认,生产者需要移除所有小于等于确认的deliveryTag的消息。
示例代码
以下是一个简单的Python示例,展示了如何使用pika库启用发布确认并处理批量确认:
Python
浅色版本
import pika
def on_delivery_confirmation(frame):
if isinstance(frame.method, pika.spec.Basic.Ack):
# 处理确认
delivery_tag = frame.method.delivery_tag
multiple = frame.method.multiple
if multiple:
# 批量确认
print(f"Batch confirmation for messages up to {delivery_tag}")
# 假设unconfirmed_messages是一个字典,键是deliveryTag
unconfirmed_messages = {tag: msg for tag, msg in unconfirmed_messages.items() if tag > delivery_tag}
else:
# 单个确认
print(f"Single confirmation for message with delivery tag {delivery_tag}")
unconfirmed_messages.pop(delivery_tag, None)
elif isinstance(frame.method, pika.spec.Basic.Nack):
# 处理否定确认
delivery_tag = frame.method.delivery_tag
multiple = frame.method.multiple
if multiple:
print(f"Batch negative confirmation for messages up to {delivery_tag}")
# 同样处理未确认的消息
else:
print(f"Single negative confirmation for message with delivery tag {delivery_tag}")
# 设置连接和通道
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.confirm_delivery(on_delivery_confirmation)
# 发送消息
for i in range(5):
channel.basic_publish(exchange='',
routing_key='test_queue',
body=f'Message {i}',
properties=pika.BasicProperties(delivery_mode=2)) # 持久化消息
# 等待确认
while len(unconfirmed_messages) > 0:
connection.process_data_events(time_limit=1)
connection.close()
在这个示例中,on_delivery_confirmation函数处理确认和否定确认,根据multiple标志来决定是否进行批量确认。unconfirmed_messages是一个假设的数据结构,用于跟踪未确认的消息。
消息队列中的数据,如果迟迟没有消费者来处理,那么就会一直占用消息队列的空间。比如我们模拟一下抢车票的场景,用户下单高铁票之后,会进行抢座,然后再进行付款,但是如果用户下单之后并没有及时的付款,这张票不可能一直让这个用户占用着,因为你不买别人还要买呢,所以会在一段时间后超时,让这张票可以继续被其他人购买。
这时,我们就可以使用死信队列,将那些用户超时未付款的或是用户主动取消的订单,进行进一步的处理,以下类型的消息都会被判定为死信:
-
消息被拒绝(basic.reject / basic.nack),并且requeue = false
-
消息TTL过期
-
队列达到最大长度