compensating transactions: when acid is too much
DESCRIPTION
The talk was presented by Dr Paul Robinson (Red Hat) at the London JBoss User Group event on the 25th of September 2013. Video available soon ACID transactions are a useful tool for application developers and can provide very strong guarantees, even in the presence of failures. However, ACID transactions are not always appropriate for every situation. ACID transactions are achieved by holding locks on resources and require the ability to rollback changes. In some situations, the blocking nature of the protocol can be too limiting to performance, especially if the transaction is distributed. Also, some actions can’t simply be rolled back; for example, sending an email. A common strategy for applications that can’t use ACID, is to throw out transactions altogether. However, with this approach you are missing out on many of the benefits that transactions can provide. There are alternative transaction models that relax some of the ACID properties, while still retaining many of the strong guarantees essential for building robust enterprise applications. These should be considered before deciding not to use transactions at all. In this talk, I’ll present one such alternative to ACID transactions: compensation-based transactions. I’ll provide an overview of ACID and it’s limitations and describe some use-cases where ACID is not appropriate. I’ll then present our new API for compensation-based transactions and demonstrate how it can be used to address these problems. Finally, I’ll present our future plans to improve and expand our support for compensation-based transactions.TRANSCRIPT
Compensating Transactions: When ACID is Too Much
Dr Paul Robinson [email protected] @pfrobinson
Agenda • Background • Non-transactional resources • Cross-domain distributed transactions • Long-lived transactions • What we have today & planned • Getting started
ACID Transactions Positives
• Strong guarantees • Tolerate (certain) failures • Easy API to develop against
Negatives • Blocking • Can reduce throughput • Requires two-phase aware resources • Tight-coupling
ACID transactions not suitable?
Don’t give up on transactions altogether!
Extended Transactions • Umbrella term • Alternative to ACID • Relaxes some ACID properties
Guarantees
None ACID Extended
Compensation-based Transactions
• Based on Sagas • Academic research from 1987
• ACID vs Compensation-based transactions • ACID
• Phase <=1: acquire locks & log • Phase 2: commit/rollback changes
• Compensation-based • Phase <=1: commit changes & log • Phase 2: confirm? / compensate change
Hang on….
What effect does this have on Isolation and Consistency?
Looks a bit dubious to me!
Isolation: ACID
Isolation: Compensations
Previous Support in Narayana • WS-BusinessActivity
• Oasis Web Services standard • Standardizes
• Message format • State machine • No API
• Problems? • Web services only • Low-level API
Compensations API • JTA-like API
• Application API only • Maybe AS and RM in future
• Interop with JTA 1.2 • Transport Neutral
Onto the examples…
Non-Transactional Resources • Transactional Resources
• Participate in a two-phase protocol • Prepare and later commit/rollback
• Non-transactional resources
• Can’t participate in a two-phase protocol
Compensation-based transaction is an option
Code Example • Ecommerce site, selling books • Coordinates:
• Updating databases • Dispatching package
Service public class BookService { @Inject PackageDispatcher packageDispatcher ; @Compensatable public void buyBook(String item, String address) { packageDispatcher.dispatch(item, address); //other activities, such as updating inventory and charging the customer } }
Non-transactional Resource public class PackageDispatcher { @Inject OrderData orderData; @TxCompensate(RecallPackage.class) public void dispatch(String item, String address) { orderData.setAddress(address); orderData.setItem(item); //Dispatch the package } }
Data @CompensationScoped public class OrderData implements Serializable { private String item; private String address; ... }
Compensation Handler public class RecallPackage implements CompensationHandler { @Inject OrderData orderData; @Override public void compensate() { //Recall the package somehow } }
Cross-Domain Distributed Transactions
• Distribution => Increased chance of failure • Use transactions!
• Distribution => Increased latency • Maybe not ACID transactions then
• Cross-domain => loose coupling • ACID transactions => tight-coupling
Compensation-based transaction is an option
Code Example • Travel Agent • Coordinates:
• Booking of a Taxi • Booking of a Hotel
• Taxi and Hotel Service are remote Web Services • WS-BA
Client public class Client { @Compensatable public void makeBooking() { // Lookup Hotel and Taxi Web Service ports here... hotelService.makeBooking("Double", "[email protected]"); taxiService.makeBooking("Newcastle", "[email protected]"); } }
Service @WebService public class HotelService { @Inject BookingData bookingData; @Compensatable(MANDATORY) @TxCompensate(CancelBooking.class) @TxConfirm(ConfirmBooking.class) @Transactional(REQUIRES_NEW) @WebMethod public void makeBooking(String item, String user) { //Update the database to mark the booking as pending… bookingData.setBookingID("the id of the booking goes here"); } }
Confirmation Handler public class ConfirmBooking implements ConfirmationHandler { @Inject BookingData bookingData; @Transactional(REQUIRES_NEW) public void confirm() { //Confirm order for bookingData.getBookingID() in Database (in a new JTA transaction) } }
Compensation Handler public class CancelBooking implements CompensationHandler { @Inject BookingData bookingData; @Transactional(REQUIRES_NEW) public void compensate() { //Cancel order for bookingData.getBookingID() in Database (in a new JTA transaction) } }
Long Lived Transactions (LLT) • ACID Transactions => all or nothing
• OK for short lived transactions (SLT) • Failure in LLT leads to significant loss of work • Compensation-based Transactions
• Split work into many SLT • Find alternative if one fails • Compensate all if no alternative
Code Example • Travel Agent • Coordinates:
• Hotel service • 2 Taxi Services
• Aim to book 1xHotel & 1xTaxi • Hotel booking is important
Travel Agent Client public class Agent { @Inject ... @Compensatable public void makeBooking(String email, String room, String dest) throws BookingException { hotelService.makeBooking(room, email); try { taxi1Service.makeBooking(dest, email); } catch (BookingException e) { taxi2Service.makeBooking(dest, email); } } }
What we Have Today • Initial version of the API
• @Compensatable • @CompensationScoped • LLT
• Distribution over WS-BA • Quickstarts
• All today’s examples • Blog post series • Available in:
• Narayana 5.0.0.M4 • WildFly 8.0.0.Alpha4
What we Have Planned • Support more complex use-cases
• Feedback driven • Recovery
• @CompensationScoped • JTA interop
• EJB support • Specification • Throughput comparisons • 2PC participants • NoSQL RM integration
Getting Started • Explore the quickstarts
• http://github.com/jbosstm/quickstart/ • Give feedback
• http://community.jboss.org/en/jbosstm • Track issues
• http://issues.jboss.org/browse/JBTM • TXFramework component
• Subscribe to Blog • http://jbossts.blogspot.co.uk/
• Contact me • [email protected], @pfrobinson