MQ的持久化分为三个部分:
一、Exchange(交换机持久化)
MQ做为消息中间件,主要用在程序间通信。使用spring集成rabbitmq后,在xml配置文件,可以很方便的设置是否持久化,代码如下:
<!-- 定义交换器 -->
<rabbit:fanout-exchange name="AMC_TMP_EXCHANGE" auto-declare="true" durable="true">
<rabbit:bindings>
<rabbit:binding queue="AMC_TMP_QUEUE"/>
</rabbit:bindings>
</rabbit:fanout-exchange>
其中 durable=true表示持久化,默认就是true,不配置这个参数也一样。
二、queue(队列持久化)
<!--定义队列-->
<rabbit:queue name="AMC_TMP_QUEUE" auto-declare="true" durable="true"/>
----2017.11.13日 补充持久化工作机制
让我们再来看一下持久化是如何工作的?
Rabbitmq会记录四种类型的内部元数据:
队列元数据:队列名称、属性(是否持久化、是否自动删除)
交换机元数据:交换机名称、类型(direct、fanout、topic)、属性(是否持久化)
绑定元数据:一张记录了交换机和队列绑定关系,和路由规则的表格
vhost元数据:为vhost内的队列、交换机和绑定提供命名空间和安全属性
上面的元数据默认保存在内存中,当我们把queue和Exchange设置成持久化后,将会保存到磁盘上,Rabbitmq重启后读取以上元数据,自动创建并绑定到一起。
文件存储位置:
rabbitmq_server-3.6.10/var/lib/rabbitmq/mnesia/rabbit@localhost
Rabbitmq目录下面的var文件夹,localhost是的主机名,mnesia是内建在Erlang的非SQL型数据库。
------
三、消息持久化
做到上面两步就真的持久化了吗?消息在server中间传递的时候断电,重启后Exchange和queue还在,那条消息还在吗?MQ会重新发送吗?
在《rabbitmq实战》一书中讲到消息持久化的问题,只有将消息也设置成持久化才是真正的持久化。
让我们查看源码:
消息Message有一个MessageProperties属性, MessageProperties指定了消息的发送模式,这里的MessageDeliveryMode.PERSISTENT表示持久化的意思:
public class MessageProperties implements Serializable {
static final String DEFAULT_CONTENT_TYPE = CONTENT_TYPE_BYTES;
static final MessageDeliveryMode DEFAULT_DELIVERY_MODE = MessageDeliveryMode.PERSISTENT;//默认消息是持久化
大功告成,让我们测试一下吧!
下面是java代码,使用了spring整合后的rabbitTemplate
public class PublishStart {
private static final Logger log = LoggerFactory.getLogger(PublishStart.class);
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-publish-rabbitMQ.xml");
RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);
rabbitTemplate.convertAndSend("< publish message 内容为:" + new Date().toString() + " >");
2017-11-05 22:03:14,843 [main]
[org.springframework.amqp.rabbit.core.RabbitTemplate]-[DEBUG]
Executing callback RabbitTemplate$$Lambda$4/1798219673 on RabbitMQ Channel: Cached Rabbit Channel:
AMQChannel(amqp://zcjlq@127.0.0.1:5672//vhostjlq,1), conn: Proxy@4e08711f Shared Rabbit Connection:
SimpleConnection@74e52ef6 [delegate=amqp://zcjlq@127.0.0.1:5672//vhostjlq, localPort= 57523]
2017-11-05 22:03:14,843 [main]
[org.springframework.amqp.rabbit.core.RabbitTemplate]-
[DEBUG] Publishing message
(Body:'< publish message 内容为:Sun Nov 05 22:03:14 CST 2017 >'
MessageProperties [headers={}, contentType=text/plain,
contentEncoding=UTF-8, contentLength=58, deliveryMode=PERSISTENT,
priority=0, deliveryTag=0])on exchange [AMC_TMP_EXCHANGE], routingKey = []
倒数第二行显示确实是持久化 deliveryMode=PERSISTENT
MQ持久化是将消息记录到磁盘,对性能有影响,但是一般情况下为了消息可靠允许性能损失。
还有一种情况是事务,但是事务对性能影响极大,大概降低2-10倍吞吐量,而且会使生产者应用程序产生同步,rabbitmq团队想到了另外一个方案:发送方确认模式,和事务类似。后面文章再做介绍。