消息的持久化是消息隊列必備的功能之一。在這篇文章中,就介紹一下RabbitMQ的持久化機制,和它的使用。
隊列的持久化
在前幾篇的例子中,我們常常看到如下定義queue的方法:
channel.QueueDeclare("Q1", false, false, false, null);
方法的第四的參數autoDelete,一般都會輸入false。文檔描述這個參數如果是true的話,意思是:如果這個queue不再使用(沒有被訂閱)的話,server就會刪除它。在我的測試過程中,只要是連接改queue的所有接收者都斷開連接的話,該queue就會被刪除,即使里面還有沒有處理的消息。RabbitMQ的重啟也同樣會刪除他們。如果輸入的是false,那與之相連的客戶端都斷開連接的話,服務是不會刪除這個隊列的,隊列中的消息也就會存在。發送端在沒有客戶端連接的時候也可以把消息放入改隊列,客戶端起來的時候,就會得到這些消息。但是如果RabbitMQ服務重啟的話,該隊列就沒有了,里面的消息自然也就沒有了。
第三個參數是exclusive,文檔描述說,如果是true,那么申明這個queue的connection斷了,那么這個隊列就被刪除了,包括里面的消息。
第二個參數durable,文檔描述說,如果是true,則代表是一個持久的隊列,那么在服務重啟后,也會存在。因為服務會把持久化的queue存放在硬盤上,放服務重啟的時候,會重新申明這個queue。當然必須是在autoDelete和exclusive都為false的時候。隊列是可以被持久化,但是里面的消息是否為持久化那還要看消息的持久化設置。也就是說,如果重啟之前那個queue里面還有沒有發出去的消息的話,重啟之后那隊列里面是不是還存在原來的消息,這個就要取決於發送者在發送消息時對消息的設置了。
消息的持久化
接上文,如果要在重啟后保持消息的持久化必須設置這個消息是持久化的。設置是在發送者發送的時候,比較簡單,代碼如下:
IBasicProperties properties = channel.CreateBasicProperties();
properties.DeliveryMode = 2;
channel.BasicPublish("", "TaskQueue", properties, bytes);
DeliveryMode等於2就說明這個消息是persistent的。1是默認是,不是持久的。
在接收者接收消息並處理的時候會出現各種各樣的問題:拋出異常導致與RabbitMQ連接斷開,程序掛掉,網絡問題等等。往往在出現這些問題的時候我們通常都希望隊列能保存這些消息,並在程序再次起來的時候能夠重新處理,或如果是負載均衡的模式下,能夠把這個消息重新分配給其他的同等的接受者來處理。這同樣也是RabbitMQ對消息持久化的一種功能。這我們在消息的傳輸控制中做詳細的說明。