Two-phase commit (2PC)
Two-phase commit protocol between the transaction manager and all
the resources enlisted for a transaction ensures that either all the
resource managers commit the transaction or they all abort. In this
protocol shown in the figure below, when the application requests the
commitment of a transaction, the transaction manager issues a
PREPARE_TO_COMMIT request to all the resource managers
involved. Each of these resources may in turn send a reply indicating
whether it is ready for commit (
PREPARED) or not
NO). Only when all the resource managers are ready for a
commit, does the transaction manager issue a commit request
COMMIT) to all the resource managers. Otherwise, the
transaction manager issues a rollback request (
the transaction is rolled back.
Although 2PC guarantees the autonomy of the transaction, the required processing load is quite heavy, creating frequent update conflicts, especially when data is duplicated across multiple sites. Replication of data is a way to alleviate this conflict problem and is usable only when transaction-based update propagation is not required. Most distributed systems adopt these two methods in parallel to judiciously match the requirements of the application.
There are trade-offs between two phase commit (2PC) and replication server approaches. The fundamental difference between them is that one operates at the transaction level and the other is a periodic propagation of updates. The guidelines are to 1) keep data replication as minimal as possible, 2) keep the number of copies small, if data must be synchronized as a transaction, and use 2PC, 3) use replication servers if concurrency requirements outweigh sub-second data integrity requirements, and 4) use replication servers if the network and nodes are unreliable.
Concurrency control is another crucial functionality. It allows multiple users to access data at the same time, increasing the throughput and performance of the system. It allows transactions to execute concurrently while achieving the same logical result as if they had executed serially. Concurrency control allows multiple transactions to read and update data simultaneously, and it includes transaction scheduling and management of the resources needed by transactions during execution. Most of the methods to ensure serialization of transactions are lock based, e.g., two-phase-locking method, timestamp method, and multiversion method. The Two-phase locking (2PL) algorithm is the most commonly used technique in distributed transactional systems to accomplish update synchronization and concurrency control. Often vendors combine concurrency control techniques like 2PL, consistency control techniques like 2PC, and timeout for deadlock resolution into a single implementation for global distributed transaction management.
Queued transaction processing
Direct transaction processing is synchronous, since the initiator of the transaction is blocked until the transaction manager runs the transaction. Unfortunately, there are situations where either the client or the server or the communication link between them fails. Sometimes there is even a need for priority scheduling of requests for transactions. The synchronous model of transaction processing cannot handle all these cases. This led to the development of asynchronous transaction processing models using queues. The queue is a transactional resource and operations on the queue, namely, enqueueing and dequeueing, are either made durable or completely undone depending on whether the transaction that issued the operations commits or aborts. The J2EE platform defines two mechanisms for handling queued semantics. One can use the native JMS API or one can make use of message-driven beans as defined in EJB Specification 2.0.
JMS API in transactions
The application component developer should not use the JMS
request-reply paradigm within a single transaction. Since a JMS
message is not delivered to its final destination until the
transaction commits, the receipt of the reply within the same
transaction never takes place. Because the container manages the
transactional enlistment of JMS sessions on behalf of a bean, the
parameters of the
createQueueSession(boolean transacted, int
transacted, int acknowledgeMode) methods are ignored. It is
recommended that the component developer specify that a session is
transacted and provide 0 for the value of the acknowledgement mode. It
is also important to keep in mind that the JMS
acknowledge() method either within a transaction or
within an unspecified transaction context must not be used. Message
acknowledgement in an unspecified transaction context is handled by
the container with
JMS AUTO_ACKNOWLEDGE semantics.
A message-driven bean is an asynchronous message consumer invoked by the container as a result of the arrival of a JMS message. The client's view of a message-driven bean is that of a JMS message consumer that implements some business logic running on the server. A client accesses a message-driven bean through JMS by sending messages to the JMS Destination (Queue or Topic) for which the message-driven bean class is the MessageListener. Message-driven beans have no home or remote interfaces and are stateless. They are thus like stateless session beans: all bean instances are equivalent as long as they are not involved in servicing a client message. A message-driven bean instance is created by the container to handle the message processing for the consumer. The container controls its lifetime. However, the instance variables of the message-driven bean instance can contain state across the handling of client messages.
Examples of such state include an open database connection and an object reference to an EJB object. The message-driven bean model makes developing an enterprise bean, which is asynchronously invoked to handle the processing of incoming JMS messages, as simple as developing the same functionality in any other JMS MessageListener. It also makes concurrent processing of a stream of messages possible by means of container provided pooling of message-driven bean instances.