Artemis持久订阅消息存储

时间:2019-07-30 12:54:53

标签: activemq-artemis durable-subscription

我试图了解ActiveMQ Artemis中持久订阅的工作方式。目前,我最大的问题是关于存储空间。

我想知道消息是否重复,这意味着对于每个使用者,该消息都存储在磁盘上,或者该消息是否存储在一个位置,而使用者仅知道断开连接并需要恢复的消息。

从我的测试中,我可以看到:具有固定的消息大小和已发布的消息数,无论我拥有1,2还是3个持久订阅,磁盘上占用的空间都是相同的。我已将它们断开连接,以便存储邮件,请放心。这会使我认为队列仅知道消费者返回时需要开始消费的消息索引。

但是相反,我使用iostat cmd检查了每秒写入字节数,并且我拥有的持久订阅队列越多,则该统计信息就越增长。这意味着消息是重复的。

你们还有更多信息,甚至是负责此工作的源代码。

1 个答案:

答案 0 :(得分:2)

默认情况下,ActiveMQ Artemis会将持久消息存储在一组称为“新闻”的本地文件中。在多个队列具有相同消息的情况下(例如,在同一JMS主题上有多个持久预订的情况下),实际消息数据仅被存储一次,并且每个队列都获得一个“引用”该消息。多次存储完全相同的消息数据将非常低效。

但是,值得注意的是,ActiveMQ Artemis日志文件在创建时会用零初始化,这意味着即使是“空”日志也要占用磁盘空间。因此,当邮件存储在日志中时,它们占用的磁盘空间量不会改变。现有的零将简单地被消息数据覆盖。

您可以找到ActiveMQ Artemis on GitHub的源代码。

如果要查看此行为的证据,可以使用artemis data print命令。此命令以人类可读的格式打印日记中的原始记录。如果要分别使用名为durable-client1durable-client2的客户端ID和subscriber-1subscriber-2的客户端ID分别进行2次持久订阅,而订阅名称分别为exampleTopicdata print。您发送一封邮件,最终将在日志中添加一个地址,2个队列,1条实际邮件和2个引用。您将在******************************************** 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] ... 命令输出中看到类似的内容:

let json = JSON(response.result.value!)
//if array name is blank just replace json["youArrayNameInJson"] to json[""]
 json["youArrayNameInJson"].array?.forEach({ (item) in

 let stationName = item["acf"]["station_name"].stringValue
 let stationDescription = item["acf"]["description"].stringValue
 let stationLogo = item["acf"]["logo"]["sizes"]["thumbnail"].stringValue
 let stationStreamUrl = item["acf"]["stream_url"].stringValue

           let newChannel = StaitonChannel(name: stationName, description: stationDescription, logo: stationLogo, streamUrl: stationStreamUrl)
                        self.channelArray.append(newChannel)

            })