RabbitMQ:5、高阶

存储机制

持久化的消息和非持久化的消息均可以被写入到磁盘。
持久化的消息一开始就会写入磁盘,若是能够,也会在内存中保存一部分以提升性能,当内存吃紧时会从内存中清楚。
非持久化的消息通常存储在内存中,内存吃紧时会换入到磁盘中,以节省内存空间。
这两种类型的消息的落盘处理都在RabbitMQ的”持久层“完成。算法

持久层

持久层是一个逻辑概念,包含队列索引和消息存储。性能

  • 队列索引(每一个队列一个):rabbit_queue_index 负责维护队列中落盘消息的信息,包括消息的存储地点、是否己被交付给消费者、是否己被消费者 ack 等。
    rabbit_queue_index 中以顺序(文件名从0开始累加)的段文件来进行存储,后缀为" . idx " ,每一个段文件中包含固定的 SEGMENT_ENTRY_COUNT 条记录,SEGMENT-ENTRY-COUNT 默认值为 1638 。每一个 rabbit_queue_index 从磁盘中读取消息的时候至少要在内存中维护一个段文件,因此设置 queue_index_embed_msgs_below(存储在哪一个结构的临界值) 值的时候要格外谨慎 一点点增大也可能会引发内存爆炸式的增加。
  • 消息存储(每一个节点有且只有一个):rabbit_msg_store 以键值对的形式存储消息,它被全部队列共享。
    通过 rabbit_msg)store 处理的全部消息都会以追加的方式写入到文件中,当这个文件的大小超过指定的限制(file_size_limit)关闭这个文件再建立一个新的文件以供新
    的消息写入。文件名(文件后缀是". rdq") 开始进行累加 所以文件名最小的文件也是最老的文件。在进行消息的存储时, bb 会在 ETS(Erlang Term Storage)表中记录消息
    在文件中的位置映射(Index)和文件的相关信息( FileSummary)。

消息能够存储在rabbit_queue_index中,也能够存储在在rabbit_msg_store中。最佳的配备是较小的消息存储在 rabbit queue index 中而较大的消息存储在rabbit_msg_store 中。索引

队列的结构

队列一般由rabbit_amqqueue_process和backing_queue两部分组成队列

  • rabbit_amqqueue_process:负责协议相关的消息处理
  • backing_queue:消息存储的具体形式和引擎

惰性队列

尽量地将消息存入磁盘中,在消费者消费到相应消息时才被加载到内存中。进程

内存和磁盘告警

内存或者磁盘低于配置的阈值时,RabbitMQ会暂时阻塞客户端的链接直至恢复正常。blocking:对应消费者关联的connection,这时候并不阻塞。blocked:对应发送消息的Connection,这时候阻塞。内存

流控

RabbitMQ从2.8版本之后还引入了流控来保证系统的稳定性。内存和磁盘告警至关于全局流控,一旦触发会阻塞集群中全部Connection,本流控是针对单个Connection的。
RabbitMQ 使用了一种基于信用证算法 (credit-based algorithm) 的流控机制来限制发送消息的速率以解决前面所提出的问题。
流控做用于Connection,出现邮件饱和时会阻塞。流控做用于Channel,出现性能瓶颈时会阻塞。it

解决性能瓶颈

综上,瓶颈每每发生在rabbit_amqqueue_process 中,用多个rabbit_amqqueue_process代替单个rabbit_amqqueue_process,能够充分利用上被流控的性能(声明交换器、队列、绑定关系;封装消费者;封装生产者)。io

镜像队列

避免单点问题,集群中某个节点崩溃,虽然交换器和绑定关系还能保存,队列和其上存储的消息却不能幸免于难,这是由于队列进程及其内容仅仅维持在
单个节点之上,因此一个节点的失效表现为其对应的队列不可用。
引入镜像队列的机制,能够将队列镜像到集群中的其余 Broker 节点之上,若是集群中的一个节点失效了,队列能自动地切换到镜像中的另外一个节点上以保证服务的可用性。集群

相关文章
相关标签/搜索