activemq-artemis - Artemis 持久订阅消息存储
问题描述
我试图了解 ActiveMQ Artemis 中持久订阅的工作原理。目前我最大的问题是关于存储。
我想知道消息是否重复,这意味着对于每个消费者来说,消息都存储在磁盘上,或者消息是否存储在一个地方,而消费者只知道他们断开连接并需要恢复的消息。
从我的测试中,我可以看到:对于固定的消息大小和发布的消息数量,磁盘上占用的空间是相同的,无论我有 1,2 还是 3 个持久订阅。我负责断开它们以便存储消息,不用担心。这会让我认为队列只知道消费者回来时需要开始消费的消息的索引。
但相反,我使用 iostat cmd 检查了每秒写入字节数,我拥有的持久订阅队列越多,这个统计数据增长得越多。这意味着消息是重复的。
你们是否有更多信息,甚至是负责此的源代码。
解决方案
默认情况下,ActiveMQ Artemis 将持久消息存储在一组称为“日志”的本地文件中。在多个队列具有相同消息的情况下(例如,在同一 JMS 主题上的多个持久订阅的情况下),实际消息数据仅存储一次,并且每个队列都获得对该消息的“引用”。多次存储完全相同的消息数据将非常低效。
然而,值得注意的是,ActiveMQ Artemis 日志文件在创建时初始化为零,这意味着即使是“空”日志也会占用磁盘空间。因此,当消息存储在日志中时,它们占用的磁盘空间量不会改变。现有的零将简单地被消息数据覆盖。
您可以在 GitHub 上找到 ActiveMQ Artemis 的源代码。
如果您想查看此行为的证据,您可以使用该artemis data print
命令。此命令以人类可读的格式打印来自日志的原始记录。如果您有 2 个持久订阅,使用客户端 IDdurable-client1
和durable-client2
订阅名称和订阅名称subscriber-1
分别subscriber-2
在名为的 JMS 主题上exampleTopic
发送一条消息,您最终会得到一个地址、2 个队列、1 条实际消息和 2 个日志中的引用. data print
您会在命令输出中看到类似这样的内容:
********************************************
B I N D I N G S J O U R N A L
********************************************
...
### Surviving Records Summary ###
...
recordID=2;userRecordType=44;isUpdate=false;compactCount=0;PersistentAddressBindingEncoding [id=2, name=exampleTopic, routingTypes={MULTICAST}, autoCreated=false]
recordID=18;userRecordType=21;isUpdate=false;compactCount=0;PersistentQueueBindingEncoding [id=18, name=durable-client1.subscriber-1, address=exampleTopic, filterString=null, user=null, autoCreated=false, maxConsumers=-1, purgeOnNoConsumers=false, exclusive=false, lastValue=false, lastValueKey=null, nonDestructive=false, consumersBeforeDispatch=0, delayBeforeDispatch=-1, routingType=0, configurationManaged=false, groupRebalance=false, groupBuckets=-1, groupFirstKey=null, autoDelete=false, autoDeleteDelay=0, autoDeleteMessageCount=0]
recordID=23;userRecordType=21;isUpdate=false;compactCount=0;PersistentQueueBindingEncoding [id=23, name=durable-client1.subscriber-2, address=exampleTopic, filterString=null, user=null, autoCreated=false, maxConsumers=-1, purgeOnNoConsumers=false, exclusive=false, lastValue=false, lastValueKey=null, nonDestructive=false, consumersBeforeDispatch=0, delayBeforeDispatch=-1, routingType=0, configurationManaged=false, groupRebalance=false, groupBuckets=-1, groupFirstKey=null, autoDelete=false, autoDeleteDelay=0, autoDeleteMessageCount=0]
...
********************************************
M E S S A G E S J O U R N A L
********************************************
...
### Surviving Records Summary ###
recordID=27;userRecordType=45;isUpdate=false;compactCount=0;Message(messageID=27;userMessageID=41705395-b2d1-11e9-91f9-a0afbd82eaba;msg=CoreMessage[messageID=27,durable=true,userID=41705395-b2d1-11e9-91f9-a0afbd82eaba,priority=4, timestamp=Tue Jul 30 08:52:22 CDT 2019,expiration=0, durable=true, address=exampleTopic,size=232,properties=TypedProperties[__AMQ_CID=durable-client1,_AMQ_ROUTING_TYPE=0]]@454305524
recordID=27;userRecordType=32;isUpdate=true;compactCount=0;AddRef;QueueEncoding [queueID=18]
recordID=27;userRecordType=32;isUpdate=true;compactCount=0;AddRef;QueueEncoding [queueID=23]
...
推荐阅读
- javascript - TensorFlow Estimator 到 TensorFlow JS
- python-3.x - 出现错误:即使我安装了烧瓶,VSCode 中的“没有名为烧瓶的模块”
- gmail-api - 如何在谷歌表格单元格中显示我的 gmail 中的电子邮件总数
- windows - WinSCP 错误 5 访问被拒绝,同时通过命令行下载
- apache - Apache 2.4 和 /tmp 中的别名
- reactjs - Ant 设计日期和时间选择器不通过 Formik 传递值(反应)
- javascript - 嵌套函数中的同名变量
- c++ - 测试身份验证 desktop_app 时的 Firebase 内部错误
- node.js - throw new TypeError('app.use() 需要中间件函数'); 会话错误
- windows - 如何在 Windows 上使用 ssh 和 IPV6 连接到 GIT 远程存储库