一、前言 |
之前我们讲,RabbitMQ server是采用轮询的方式,公平的依次给每一个消费者。下面我们就来讲讲RabbitMQ 是如何把消息持久化的。
1.1、RabbitMQ手动确认
是消费者处理消息完毕之后,需要RabbitMQ server手动去确认是否处理完毕,而不是自动确认。
通过 rabbitmqctl list_queues查看队列的消息。
如果想要清楚消息,则需要手动确认。确认代码如下:
ch.basic_ack(delivery_tag=method.delivery_tag)

#!/usr/bin/env python #-*- coding:utf-8 -*- __author = "susu" ## 消费者有可能在其他的机器上 import pika,time credentials = pika.PlainCredentials('junesu', '123456') #连接信息 connection = pika.BlockingConnection(pika.ConnectionParameters( '192.168.5.132',5672,'/',credentials)) channel = connection.channel() channel.queue_declare(queue="xiaosusu") def callback(ch, method, properites, body): print("--->", ch, method, properites) # time.sleep(30) print(" [x] Received %r" % body) ch.basic_ack(delivery_tag=method.delivery_tag) channel.basic_consume( callback, queue="xiaosusu", # no_ack=True ) print(' [*] Waiting for messages. To exit press CTRL+C') channel.start_consuming()
再来看看效果
1.2、消息处理完毕,为什么需要手动确认一下呢?
因为你调用的这个callback函数之后,它可能处理完收到这个消息,它接下来要干很多事情,就是说跟这个消息没有关系了。就是函数没有处理完,但是消息已经处理完了,所以你要等到函数处理完可能要花2个消息,那服务器要等2个小时候之后才能收到,所以这个也是手动确认也会处理。
二、RabbitMQ消息持久化 |
队列里面还为消息等着客户端(消费者)去接收,但是这个时候服务器端down机了,这个时候消息是否还在?带着这个疑问,我们来做几个实验。
2.1、重启队列和消息丢失
说明:服务端发送消息->重启RabbitMQ
服务端传统的声明queue
channel.queue_declare(queue="xiaoxiaosu")
这种情况下消息都在内存里面,如果down了就down了,队列和消息都没有了
2.2、队列持久化
说明:我们把队列进行持久化,就算重启我的RabbitMQ服务,我的队列也不会丢。
队列持久化,在服务端(生产者)声明queue的时候,需如下定义:
channel.queue_declare(queue='xiaosusu', durable=True)#durable=>持久化
2.3、队列和消息都持久化
说明:现在我想队列和消息都持久化,那怎么办呢。
队列和消息都持久化,在服务端(生产者)声明queue的时候,需如下定义:
channel.queue_declare(queue="xiaosusu",durable=True) #durable=>持久化 channel.basic_publish(exchange="", routing_key="xiaosusu", #queue的名字 body="hello world", properties=pika.BasicProperties(delivery_mode=2,) # make message persistent=>使消息持久化 ) #body是你发送的内容
总结:如果想队列和消息都保证持久化,就必须是声明和发消息的时候,都需要声明持久化。
注:如果你在服务端声明持久化,在客户端也必须声明queue的时候也需要声明持久化,不然的话就会报错,声明持久化的方式和服务端一样
四、总结 |
- RabbitMQ在服务端没有声明队列queue持久化(durable=True)时,队列是存在内存中的,服务端down机了,队列也随之消失。
- RabbitMQ在服务端只声明queue持久化,但是在发送消息时,没有声明持久化(properties=pika.BasicProperties(delivery_mode=2,)),服务器down机,只保留队列,但是不保留消息。
- RabbitMQ在服务端声明queue持久化,并且在发消息时也声明了持久化,服务down机重启后,队列和消息都能得到保存。
- 服务端声明持久化,客户端想接受消息的话,必须也要声明queue时,也要声明持久化,不然的话,客户端执行会报错。