1. RabbitMQ 持久化机制
RabbitMQ 的持久化分为队列持久化、消息持久化和交换器持久化。
不管是持久化的消息还是非持久化的消息都可以被写入到磁盘。区别在于重启之后数据还在不在。
-
持久化
-
非持久化
1. 队列持久化
- 队列的持久化是在定义队列时的 durable 参数来实现的,durable 为 true 时,队列才会持久化。
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
// 第二个参数设置为 true,则 durable=true
channel.queueDeclare("queue1", true, false, false, null);
- 持久化的队列在管理界面可以看到有个“D”的标识。
2. 消息持久化
- 消息持久化通过消息的属性 deliveryMode 来设置是否持久化,在发送消息时通过 basicPublish 的参数传入。
// 通过传入 MessageProperties.PERSISTENT_TEXT_PLAIN 就可以实现消息持久化。
channel.basicPublish("", "queue1", MessageProperties.PERSISTENT_TEXT_PLAIN, "persistent_test_message".getBytes());
3. 交换器持久化
- 同队列一样,交换器也需要在定义时设置持久化标识,否则在 Broker 重启后数据将丢失。
// durable 为 true 则开启持久化
Exchange.DeclareOk exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable) throws IOException;
2. RabbitMQ 内存控制
- 当内存使用超过配置的阀值,RabbitMQ 会暂停阻塞客户端的连接,并停止接收从客户端发来的消息,以此避免服务崩溃,客户端与服务端的心跳检测也会失效。
rabbitmqctl set_vm_memory_hight_watermark <fraction>
-
fraction 为内存储值,RabbitMQ 默认是 0.4,表示当 RabbitMQ 使用的内存超过 40% 时,就会产生告警并阻塞所有生产者连接。
-
通过此命令修改的阀值在 Broker 重启后将会失效,通过修改配置文件的方式修改的阀值,则不会在重启后消失,但需要重启 Broker 才会生效。
-
配置文件地址:/etc/rabbitmq/rabbitmq.conf
vm_memory_high_watermark.relative = 0.4 # vm_memory_high_watermark.absolute = 1GB
-
RabbitMQ 提供了 relative 或 absolute 两种配置方式:
- relative 相对值,即前面的 fraction,建议取值在 0.4~0.66 之间,不建议超过 0.7
- absolute 绝对值,单位为 KB、MB、GB,对应的命令是
rabbitmqctl set_vm_memory_high_watermark absolute <value>
RabbitMQ 内存换页
-
在某个 Broker 节点触及内存并阻塞生产者之前,它会尝试将队列中的消息换页到磁盘以释放内存空间。持久化和非持久化的消息都会被转储到磁盘中,其中持久化的消息本身就在磁盘中有一份副本,这里会将持久化的消息从内存中清除掉。
-
默认情况下,在内存到达内存阀值的 50% 时会进行换页动作。也就是说,在默认的内存阀值为 0.4 的情况下,当内存超过 0.4x0.5=0.2 时会进行换页动作。
-
可以通过在配置文件中配置 vm_memory_high_watermark_paging_ratio 项来修改此值:
vm_memory_high_watermark.relative = 0.4 vm_memory_high_watermark_paging_ratio = 0.75
-
以上配置将会在 RabbitMQ 内存使用率达到 30% 时进行换页动作,并在 40% 时阻塞生产者。
-
当 vm_memory_high_watermark_paging_ratio 的值大于 1 时,相当于禁用了换页功能。
3. RabbitMQ 磁盘控制
1. RabbitMQ 磁盘告警
-
当磁盘剩余空间低于确定的阀值时,RabbitMQ 同样会阻塞生产者,这样可以避免因非持久化的消息持续换页而耗尽磁盘空间导致服务崩溃。
-
默认情况下,磁盘阀值为 50MB,表示当磁盘空间低于 50MB 时会阻塞生产者并停止内存中消息的换页动作。
-
这个阀值的设置可以减小,但不能完全消除磁盘耗尽而导致崩溃的可能性。比如在两次磁盘空间检测期间内,磁盘空间从大于 50MB 被耗尽到 0MB。
-
一个相对谨慎的做法是将磁盘阀值设置为与操作系统所显示的内存大小一致。
2. RabbitMQ 磁盘控制
-
通过命令可以临时调整磁盘阀值
rabbitmqctl set_disk_free_limit <disk_limit> rabbitmqctl set_disk_free_limit mem_relative <fraction>
- disk_limit 为固定大小,单位为 KB、MB、GB。
- fraction 为相对值大小,建议的取值为 1.0~2.0 之间。
-
对应的配置如下:
disk_free_limit.relative = 2.0 # disk_free_limit.absolute = 50mb