关于ActiveMQ Artemis持久订阅消息存储机制的技术问询
Great question—your test observations perfectly highlight the nuance of how Artemis handles durable subscription storage, and there’s a clear explanation for the seemingly conflicting results you’re seeing.
Core Storage Mechanism: One Message Copy, Multiple Subscription Pointers
First, let’s clarify the big picture: Artemis only stores the message body once on disk, regardless of how many durable subscriptions exist for the topic. Here’s how it works:
- When a message is published to a topic with durable subscriptions, the broker writes the full message payload to its main message journal just once.
- Each durable subscription doesn’t get its own copy of the message. Instead, it only stores a small piece of metadata: the last acknowledged message position (essentially an index or offset pointing to the message in the shared journal). This is what allows the subscription to resume consumption exactly where it left off when reconnecting.
That’s why your disk space test showed no difference with 1, 2, or 3 durable subscriptions—the bulk storage (the message itself) is shared, and the per-subscription metadata is tiny enough that it doesn’t move the needle on total disk usage.
Why iostat Shows Higher Writes With More Subscriptions
The increase in write bytes you’re seeing via iostat isn’t from duplicating message bodies—it’s from the per-subscription metadata updates. Here’s the breakdown:
- For each message published, Artemis needs to track that the message is available for every active durable subscription. This means writing small journal entries for each subscription to update its cursor position (the next message it needs to consume).
- Even if the consumers are disconnected, the broker still needs to record that the message is pending for each durable subscription. Each of these pending message entries is a small metadata write, not a full message copy.
- More subscriptions = more of these small metadata writes per published message, which adds up to higher total write throughput as seen in
iostat, even though the actual message data is only written once.
Key Source Code References
If you want to dive into the implementation, here are the critical classes responsible for this logic:
org.apache.activemq.artemis.core.persistence.impl.journal.JournalStorageManager: Handles the core message persistence logic. Look for methods likestoreMessage—this is where the message body is written once to the journal.org.apache.activemq.artemis.core.server.impl.QueueImpl(specificallyDurableQueuefor durable subscriptions): Manages the subscription’s cursor (PersistentQueueCursor), which tracks the subscription’s consumption position. The cursor’s state (including pending message positions) is persisted via journal writes.org.apache.activemq.artemis.core.persistence.impl.journal.BindingJournalStorageManager: Deals with the persistence of subscription/queue metadata, including the durable subscription’s configuration and cursor state.
Recap of Your Test Results
- Static disk usage: Because message bodies are stored once, and per-subscription metadata is negligible in size.
- Higher
iostatwrites: Because each subscription requires a small journal entry to track pending messages, multiplying the number of write operations per published message.
内容的提问来源于stack exchange,提问作者Artandor

