代码编织梦想

http://previous.rabbitmq.com/v3_6_x/persistence-conf.html

RabbitMQ持久化层的目的是在大多数没有配置的情况下提供良好的结果。然而,某些配置有时是有用的。本页面解释如何配置它。建议你在采取任何行动之前把它全部读完。

持久化工作原理

持久化消息和非持久化消息均可被写入磁盘。持久化消息一到达队列就会被写入磁盘,非持久化消息只有在内存压力下才会被写入磁盘。在可能的情况下,持久化消息也保存在内存中,并且仅在内存压力下才从内存中取出。“持久化层”指用于将这两种类型的消息存储到磁盘的机制。

On this page we say "queue" to refer to an unmirrored queue or a queue master or a queue slave. Queue mirroring happens "above" persistence. 

持久化层有两个组件:queue index和message store。queue index负责维护给定消息在队列中的位置、是否交付(deliverd)和是否确认(acknowledged)。因此,每个队列都有一个队列索引。(There is therefore one queue index per queue.)

message store是消息的key-value存储,在服务器中的所有队列上共享。消息(主体、任何属性和/或header)可以直接存储在队列索引中,也可以写入消息存储中。从技术上讲,有两个消息存储(一个用于临时消息,一个用于持久消息),但它们通常被认为是“message store”。 

内存占用

在内存压力下,持久化层试图将尽可能多的数据写到磁盘上,并从内存中删除尽可能多的数据。然而,有些内容必须留在内存中:

  •  每个队列为每个未确认的消息维护一些元数据。如果消息本身的目的地是msg store,则可以从内存中删除消息本身。
  • msg store需要一个index.默认的msg store index为存储中的每条消息使用少量内存。The message store needs an index. The default message store index uses a small amount of memory for every message in the store.

 queue index中的消息(message)

将消息写入队列索引有优点也有缺点。

优点:

  • 消息可以在一个操作中写入磁盘,而不是两个;对于微小的消息,这可能是一个巨大的收益。
  • 写入队列索引的消息不需要消息存储索引中的条目,因此在换出时不需要内存成本。

缺点:

  • 队列索引在内存中保存固定数量的记录块;如果将非微型消息写入队列索引,则内存使用可能非常大。
  • 如果交换器将消息路由到多个队列,则需要将消息写入多个队列索引。如果将这样的消息写入消息存储,只需要写入一个副本。
  • 目的地为队列索引的未确认消息始终保存在内存中。Unacknowledged messages whose destination is the queue index are always kept in memory.

其目的是将非常小的消息作为优化存储在队列索引中,并将所有其他消息写入消息存储中。这是由配置项 queue_index_embed_msgs_below来控制的。默认情况下,序列化大小小于4096字节(包括属性和头部)的消息存储在队列索引中。

从磁盘读取消息时,每个队列索引至少需要在内存中保留一个段文件。段文件包含16384条消息的记录。因此,在增加queue_index_embed_msgs_below时要小心;一点点增加也可能导致内存的大量增长。

 

 

持久化性能可能表现不佳,因为持久化受限于必须处理的文件句柄或异步线程的数量。在这两种情况下,当您有大量队列需要同时访问磁盘时,都可能发生这种情况。

文件句柄过少

RabbitMQ服务器通常限制它可以打开的文件句柄的数量(无论如何,在Unix上)。每个正在运行的网络连接都需要一个文件句柄,其余的文件句柄可供队列使用。如果在考虑网络连接之后,磁盘访问队列多于文件句柄,那么磁盘访问队列将在它们之间共享文件句柄;每个都可以使用文件句柄一段时间,然后将其收回并交给另一个队列。

这可以防止服务器由于有太多磁盘访问队列而崩溃,但是这会变得非常昂贵。管理插件可以显示集群中每个节点的I/O统计信息;除了显示读、写、查找等的速率外,它还将显示重新打开的速率(reopen)——以这种方式回收文件句柄的速率。一个文件句柄太少的繁忙服务器可能每秒要重新打开数百次(reopen)——在这种情况下,如果有更多的文件句柄,它的性能可能会显著提高。

异步线程过少

Erlang虚拟机创建一个异步线程池来处理长时间运行的文件I/O操作。这些在所有队列之间共享。每个活动的文件I/O操作在进行时使用一个异步线程。因此,异步线程太少会损害性能。

注意,异步线程的情况与文件句柄的情况并不完全相同。如果一个队列按顺序执行许多I/O操作,那么如果它为所有操作保留一个文件句柄,它将执行得最好;否则,我们可能会频繁flush和seek,并使用额外的CPU编排它。然而,队列不能从跨操作序列持有异步线程中获益(事实上,它们不能这样做)。However, queues do not benefit from holding an async thread across a sequence of operations (in fact they cannot do so). 

因此,理想情况下,应该有足够的文件句柄来处理所有正在执行I/O操作流的队列,并且应该有足够的异步线程来处理存储层可以执行的并发I/O操作的数量。

当缺乏异步线程导致性能问题时,情况就不那么明显了。(一般来说也不太可能;先检查其他东西!)异步线程过少的典型症状包括,在服务器应该忙于持久化而每个I/O操作的报告时间增加的短时间内,每秒的I/O操作数降为零。

异步线程的数量由这里描述的Erlang虚拟机的+A参数配置,通常通过环境变量RABBITMQ_SERVER_ERL_ARGS配置。默认值是+A 64。在更改此值之前,尝试几个不同的值可能是一个好主意。

替代message store index实现

如上所述,写入message store的每个消息都为其索引项(index)使用少量内存。message store index在RabbitMQ中是可插入(pluggable)的,其他实现可以作为插件使用,从而消除这一限制。(我们没有在服务器上附带任何代码的原因是它们都使用本地代码。)注意,这些插件通常会使消息存储运行得更慢。

rabbitmq持久化机制-爱代码爱编程

之前其实已经写过一篇关于RabbitMQ持久化的 文章 ,但那篇文章侧重代码层面的写入流程,对于持久化操作何时发生以及什么时候会刷新到磁盘等问题其实都没有搞清楚,这篇文章着重于关注这些问题。 消息什么时候需要持久化? 根据 官方博文 的介绍,RabbitMQ在两种情况下会将消息写入磁盘: 消息本身在publish的时候就要求消息写入磁盘;

rabbitmq 学习 之持久化配置(29)_xiaoliuliu2050的博客-爱代码爱编程

https://www.rabbitmq.com/persistence-conf.html RabbitMQ持久化层的目的是在大多数没有配置的情况下提供良好的结果。然而,某些配置有时是有用的。本页面解释如何配置它。建议你在采取任何行动之前把它全部读完。 持久化工作原理 持久化消息和非持久化消息均可被写入磁盘。持久化消息一到达队列就会被写入磁盘,非持

rabbitmq持久化消息设置_chuixieli7527的博客-爱代码爱编程

void basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) throws IOException; channel.basicPublish("exchange.persistent", "persistent", Messag

RabbitMQ 学习笔记 -- 09 RabbitMQ 的持久化-爱代码爱编程

一、消息中间件的常见使用场景 复杂系统的解耦: 多个系统间通过中间件进行数据交互, 避免牵一发而动全身, 减少耦合, 提升系统稳定性与可扩展性复杂链路的异步调用: 某些业务场景可以通过异步执行减少同步调用的时间, 从而大大提高系统响应时间而不影响核心逻辑瞬时高峰的削峰处理: 流量高峰期, 可以将请求积压在MQ中, 服务器不用一下处理所有请求从而导致系统崩

rabbitmq:安装、配置、消息延迟与持久化-爱代码爱编程

构建带有消息延迟插件的rabbitmq镜像,下面是Dockerfile https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/latest 插件包可以在这里下载 FROM rabbitmq:management-alpine #FROM rabbitmq:manage

rabbitmq 持久化_RabbitMQ讲解-爱代码爱编程

RabbitMQ是一个在AMQP基础上实现的企业级消息系统。何谓消息系统,就是消息队列系统,消息队列是“”消费-生产者模型“”的一个典型的代表,一端往消息队列中不断写入消息,而另一端则可以读取或者订阅队列中的消息。 what?消费-生产者模型?对,没错!就是大学操作系统课程里面的“消费者-生产者模式”,记得当时被这个问题坑的不轻啊。 在项目中,将一

Springboot 整合RabbitMq,消息手动确认及持久化-爱代码爱编程

该篇文章内容较多,包括有rabbitMq相关的一些简单理论介绍,provider消息推送实例,consumer消息消费实例,Direct、Topic、Fanout的使用,消息回调、手动确认等。 (但是关于rabbitMq的安装,我的是在虚拟机上用docker安装的) 在安装完rabbitMq后,输入http://ip:15672/ ,是可以看到一个简单后

RabbitMQ—持久化-爱代码爱编程

RabbitMQ—持久化 引言 如何保障当 RabbitMQ 服务停掉以后消息生产者发送过来的消息不丢失?默认情况下 RabbitMQ 退出或由于某种原因崩溃时,它丢失队列和消息,除非告知它不要这样做。确保消息不会丢失需要做两件事:我们需要将队列和消息都标记为持久化。队列持久化 如何实现队列持久化? 在声明队列的时候把 durable 参数设置为tr

RabbitMQ消息持久化-爱代码爱编程

当RabbitMQ服务器挂了,它可能就丢失所有队列中的消息和任务。如果你想让RabbitMQ记住当前的状态和内容,就需要通过2件事来确保消息和任务不会丢失:同时将queue和messages标识为durable。 设置了队列和消息的持久化之后,当broker服务重启的之后,消息依旧存在。单只设置队列持久化,重启之后消息会丢失;单只设置消息的持久化,重启之

rabbitmq持久化_rabbitmq持久化配置-爱代码爱编程

RabbitMQ持久化 RabbitMQ消费者如果在某种情况下出现宕机,崩溃的时候是会导致消息丢失的,因此我们需要在某种特定情况下,无论是RabbitMQ服务重启、崩溃,也不会丢失消息,我们可以将Queue与Message