Apache Qpid : Queue Replay
This page last changed on Feb 20, 2007 by ritchiem.
BackgroundA lengthy discussion on replay in January 2007(page #7, Thread) highlighted a number of requirements and possible implementation options for adding replay to Qpid and AMQP. The requirements come from the desire to speed up the rate a consumer can read messages and to simplify its recovery when it starts. This page is to give some background, a proposal and finally some implementation options for discussion. HistoryWhen a an application updates the state of a single Resource Manager, e.g a database or queue manager, it normally does so within the context of a local Transaction and this transaction exhibits the following ACID properties:
Distributed TransactionA distributed transaction is typically implemented by performing a Two Phase Commit (2PC) over which there are several varients the most well know being the X/Open XA specification. Where both the middleware and the consumer support XA, a separate Transaction Manager isused to coordinate the local transactions. The transaction manager coordinates atomicity at the global level whist each resource manager is responsible for the ACID properties of its local transactions. These benefits do not come without cost.
Idempotence and ReplayingWhen a message is being moved from system A to system B (e.g. from WebSphereMQ to ORACLE), distributed transactions can be avoided if;
The most common way of doing this is simply managing the local transactions so that system B commits before system A. The start of replay is them the end of the last transaction on system A. Typically a MOM will immediately delete a message once it has been commited by all of its consumers. Commit is Not The EndIf messages are made available for replay to a consumer after it has been commited, we can stretch the point in time the consumer recovers from back to any point.
This larger recovery window lets downstream consumers the flexibility to recover from more failure scenarios.
Replay as a First Class ServiceWhen a traditional queue is opened for reading, it is opened and the next message is the oldest one that has not been destructively read (i.e. read and commited). In isolation, a consumer manages its own local transactions with the message broker to confirm when a message or group of messages is processed, stored and stable. The local transaction leads to a disk write in the queue storage to mark the messages as read. In this XA free world the consumer relys on the messaging to replay messages from the applications last good known state. As its always reading from a queue, the only extension to the queues semantics is to let it be opened for reading from a known message, irrespective of whether the message has been committed or not and it goes without saying that they should be in the same order in which they were originally delivered. Many consumers of a guaranteed message flow are writing to a database and this database is the consumers view of its state, it's certainly where the consumer recovers from when it starts up. The traditional model of using a transaction manager, typically XA, to co-ordinate the local transactions on the database and messaging broker is slow and not without its problems. Another model is to have the messaging infrastructure support replay of messages from a known point in history i.e. to correlate the current state of the consumers database with a last received message that last caused an update to the database from this channel. This is not an all encompassing pattern but rather compliments other ways to synchronize state between a message broker and a database. Requirements
Proposal: A Replayable QueueQueues are the storage agents in AMQP so are the logical point to provide replay. A Replayable Queue (RQ) is not the default queue behavior but rather has to be explicitly configured. In may ways an RQ is somewhere between a traditional queue and a transaction log such as HOWL An RQ has the following properties:
Benefits
Downsides
Implementation Options in Qpid.ConfigurationStorageManagementUsage from JMS![]() ![]() ![]() |
![]() |
Document generated by Confluence on May 26, 2010 10:33 |