文档章节

rabbitmq中消息的存储

n
 nibilly
发布于 2015/04/28 21:34
字数 1052
阅读 36
收藏 1

1. 大概原理:


所有队列中的消息都以append的方式写到一个文件中,当这个文件的大小超过指定的限制大小后,关闭这个文件再创建一个新的文件供消息的写入。文件名(*.rdq)从0开始然后依次累加。当某个消息被删除时,并不立即从文件中删除相关信息,而是做一些记录,当垃圾数据达到一定比例时,启动垃圾回收处理,将逻辑相邻的文件中的数据合并到一个文件中。


2. 消息的读写及删除:


rabbitmq在启动时会创建msg_store_persistent,msg_store_transient两个进程,一个用于持久消息的存储,一个用于内存不够时,将存储在内存中的非持久化数据转存到磁盘中。所有队列的消息的写入和删除最终都由这两个进程负责处理,而消息的读取则可能是队列本身直接打开文件进行读取,也可能是发送请求由msg_store_persisteng/msg_store_transient进程进行处理。


在进行消息的存储时,rabbitmq会在ets表中记录消息在文件中的映射,以及文件的相关信息。消息读取时,根据消息ID找到该消息所存储的文件,在文件中的偏移量,然后打开文件进行读取。消息的删除只是从ets表删除指定消息的相关信息,同时更新消息对应存储的文件的相关信息(更新文件有效数据大小)。


3. 垃圾回收:


由于执行消息删除操作时,并不立即对在文件中对消息进行删除,也就是说消息依然在文件中,仅仅是垃圾数据而已。当垃圾数据超过一定比例后(默认比例为50%),并且至少有三个及以上的文件时,rabbitmq触发垃圾回收。垃圾回收会先找到符合要求的两个文件(根据#file_summary{}中left,right找逻辑上相邻的两个文件,并且两个文件的有效数据可在一个文件中存储),然后锁定这两个文件,并先对左边文件的有效数据进行整理,再将右边文件的有效数据写入到左边文件,同时更新消息的相关信息(存储的文件,文件中的偏移量),文件的相关信息(文件的有效数据,左边文件,右边文件),最后将右边的文件删除。




4. 性能考虑:


(1)操作引用计数(flying_ets)


队列在进行消息的写入和删除操作前,会在flying_ets表里通过+1,-1的方式进行计数,然后投递请求给msg_store_persistent/msg_store_transient进程进行处理,进程在真正写操作或者删除之前会再次判断flying_ets中对应消息的计数决定是否需要进行相应操作。这样,对于频繁写入和删除的操作,概率减少实际的写入和删除。

(2)尽可能的并发读


在读取消息的时候,都先根据消息ID找到对应存储的文件,如果文件存在并且未被锁住,则直接打开文件,从指定位置读取消息的内容。


如果消息存储的文件被锁住了,或者对应的文件不存在了,则发送请求,由msg_store_persistent/msg_store_transient进程进行处理。


(3)消息缓存


1)利用ets表进行缓存 


对于当前正在写的文件,所有消息在写入前都会在cur_file_cache_ets表中存一份,消息读取时会优先从这里进行查找。文件关闭时,会将cur_file_cache_ets表中引用计数为0的消息进行清除。


2)file_handle_cache的写缓存


rabbitmq中对文件的操作封转到了file_handle_cache模块,以写模式打开文件时,默认有1M大小的缓存,即在进行文件的写操作时,是先写入到这个缓存中,当缓存超过大小或者显式刷新,才将缓存中的内容刷入磁盘中。


本文转载自:http://my.oschina.net/hncscwc/blog/182083

共有 人打赏支持
n
粉丝 14
博文 179
码字总数 41779
作品 0
厦门
消息中间件—RabbitMQ(初探篇)

文章摘要:本篇文章为RabbitMQ的入门文章,不像其他一些程序代码和应用实战性的文章会带着大家从一个“Hello World”的简单例子出发,在该篇幅中主要给大家讲下RabbitMQ消息队列的起源、为何...

癫狂侠
05/23
0
0
RabbitMQ详解(二)------消息通信的概念

  PS:近期在南宁出差,工作比较忙,所以更新会比较慢。   说到消息通信,可能我们首先会想到的是邮箱,QQ,微信,短信等等这些通信方式,这些通信方式都有发送者,接收者,还有一个中间...

ysocean
07/09
0
0
RabbitMQ与Redis做队列比较

本文仅针对RabbitMQ与Redis做队列应用时的情况进行对比 具体采用什么方式实现,还需要取决于系统的实际需求 简要介绍 RabbitMQ RabbitMQ是实现AMQP(高级消息队列协议)的消息中间件的一种,...

Edwyn王
2015/05/20
0
0
消息中间件—RabbitMQ(集群原理与搭建篇)

摘要:实际生产应用中都会采用消息队列的集群方案,如果选择RabbitMQ那么有必要了解下它的集群方案原理 一般来说,如果只是为了学习RabbitMQ或者验证业务工程的正确性那么在本地环境或者测试...

癫狂侠
05/25
0
0
ActiveMQ RabbitMQ KafKa对比

前言: ActiveMQ和 RabbitMq 以及Kafka在之前的项目中都有陆续使用过,当然对于三者没有进行过具体的对比,以下摘抄了一些网上关于这三者的对比情况,我自己看过之后感觉还 是可以的,比较清...

xiaomin0322
05/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

shell学习之创建函数

函数是一个脚本代码块,你可以为其命名并在代码中任何位置重用。 在bash shell脚本中创建函数基本使用如下两种方式,第二种格式更接近于其他编程语言中定义函数的方式。 function name {com...

woshixin
21分钟前
1
0
Toolfk.com 程序员工具网上线

#前言 真不容易,用了一个月的业余时间才把这个网站(toolfk.com)做完。里面的内容主要是从github上找的开源码码,在线运行使用的是Docker运行。当然也是现成的。因为我现在对Docker还是不懂。...

hihubs
35分钟前
2
0
svn 常用操作命令及问题处理

1. 常用命令 1.1. 基本使用 检出 checkout ➜ svn co repo_url -m '检出代码'➜ svn co repo_url saved_dir_name -m '检出代码,并指定目录名' 加入版本控制 add # 添加指定文件➜ svn...

whoru
今天
3
0
记一次jquery validate的扩展(第一次失去焦点时触发校验)

最近在用jquery.validate 做前端表单校验,但是发现每次第一次失去焦点时,如果文本框内容为空,且该字段是必填项, 则不会触发校验,直到提交表单后,再次失去焦点时,才会触发,想对此进行...

foreach
今天
1
0
java生成UUID

UUID介绍: UUID(Universally Unique Identifier)全局唯一标识符,是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。按照开放软件基金会(OSF)制定的标准计算,用到了以...

编程SHA
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部