| 一、前言 |
之前我們講,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時,也要聲明持久化,不然的話,客戶端執行會報錯。
