前言
因业务需要,项目中用到了许多延时队列,采用 RabbitMQ 的延时队列插件实现。
ps
紧急情况下,可以修改内存阈值,重启生效
echo "vm_memory_high_watermark.relative = 0.8" >> /etc/rabbitmq/rabbitmq.conf
因为和内存有关自然而然就想到,会不会是因为节点是 RAM 节点导致的,但是单节点情况下默认是 DISK 节点,所以这个可以排除。
查看内存
点击节点
内存用了好多,快撑不住了。
查看内存使用情况
可以看到 internal database tables 占用了特别多的内存
有关 internal database tables ,顾名思义,就是内部数据库的表
使用 rabbitmqctl status 命令查看内存使用情况
发现 mnesia 占用了大部分内存。
通过官方文档发现 mnesia 和 internal database tables 的关系
https://www.rabbitmq.com/memory-use.html
Mnesia 是一个分布式数据库,RabbitMQ 使用它来存储有关用户、交换器、队列和绑定的信息。
网上大部分都会说,消息不存储在数据库中,但是 rabbitmq-server 的 mkuratczyk 在 issues 回复我说,延时队列是个例外。
https://github.com/rabbitmq/rabbitmq-server/issues/5080
获取 mnesia 中各个表中数据条数
rabbitmqctl eval 'mnesia:schema().' | grep -E 'Properties|size'
root@myRabbit2:/# rabbitmqctl eval 'mnesia:schema().' | grep -E 'Properties|size'
-- Properties for gm_group table ---
size -> 0
-- Properties for mirrored_sup_childspec table ---
size -> 0
-- Properties for rabbit_delayed_messagerabbit@myRabbit2 table ---
size -> 6008272
-- Properties for rabbit_delayed_messagerabbit@myRabbit2_index table ---
size -> 1051188
-- Properties for rabbit_durable_exchange table ---
size -> 12
-- Properties for rabbit_durable_queue table ---
size -> 5
可以看到延时队列的表数据量在600w左右,这些消息都是不满足延时条件的,一旦延时条件满足,这些消息就会回到队列中,等待被消费。
问题定位完毕,因为延时队列的特殊性,消息在延时条件满足前需要存在 mnesia 中,而 mnesia 的数据会加载到内存中。