Hace unos días escribía sobre la disponibilidad de las charlas de la SpringOne 2008. Una que he leido recientemente es la de Jurgen Holler, Transaction Choices for Performance, y en la que se entra en detalle sobre los diferentes tipos de transacciones en Spring y sobre como evitar las transacciones XA en la medida de lo posible.
Muchos de los que leen este blog sabrán lo que es XA, aunque supongo que otros no. Básicamente es una especificación que define como sincronizar el acceso a recursos totalmente diferentes dentro de una misma transacción, para lo que se utilizar un gestor de transacciones global. Un ejemplo sería el realizar desde un mismo método un acceso a base de datos y enviar un mensaje a algún broker de mensajería. XA te garantiza que el método se ejecutará preservando las propiedades ACID entre las diferentes llamadas.
En el screencast de arriba( y esto es una prueba y una excusa para probar este servicio ) os muestro un caso muy típico en el que se necesitaría sincronizar una base de datos y un servidor de mensajería. El método A actualiza la base de datos, envía un mensaje a una cola, realiza un proceso y termina su ejecución. Mientras tanto, en otra parte del sistema, un consumidor lee asíncronamente el mensaje en B y consulta la base de datos. ¿Cuál es el problema? Pues que como la cola de mensajería y la base de datos tienen sus propios gestores de transacciones, resulta que es muy probable que el mensaje llegue a B cuando la transacción en A todavía no se ha persistido en la base de datos, con lo que el consumidor estaría leyendo un valor incorrecto (ver phantom reads si no se es familiar con este concepto).
Utilizar XA soluciona este problema ya que un gestor de transacciones global se encargá de sincronizar todos los recursos de forma que por ejemplo el mensaje no se envie hasta que no se haya hecho commit de la transacción (aunque en realidad dependería de la implementación del gestor transaccional). A simple vista utilizar XA parece claramente una buena idea. Sin embargo, hay un problema muy importante, XA es enormemente lento. Muchísimo más lento que utilizar transacciones simples ( o que no usar transacciones ). Jurgen desmonta unos cuantos mitos sobre las transacciones XA en su presentación:
Me permito traducir los puntos:
- Una aplicación empresarial crítica y seria necesita transacciones XA: No es cierto, muchas aplicaciones empresariales no utilizan para nada transacciones XA.
- Una mapeo objeto-relacional correcto requiere el uso de XA: No es cierto, los mapeadores objeto-relacional normalmente operan con JDBC más un sistema de caché propio.
- Para combinar JDBC y JMS las transacciones XA son obligatorias: No es cierto, muchas aplicaciones empresariales utilizan JMS con transacciones nativas o ACKs.
- Los gestores de transacciones modernos están optimizados para ofrecer el mejor rendimiento: No es cierto, las garantías que XA exige son costosas y no pueden ser optimizadas de forma tan sencilla.
Siguiendo con la presentación, la principal recomendación de Jürgen es que una de las formas para solucionar el problema planteado arriba es sincronizar de manera nativa la cola de Spring con el gestor transaccional que utiliza el DataSource de forma que el mensaje sólo se enviará cuando se termine la ejecución del primer método y se haga commit de la transacción lo que tiene la ventaja de no usar XA y tener un mayor throughput.
Es curioso además que hoy hablando con alguien, me comentaba que algunos bancos no estaba interesados en absoluto en utilizar XA, y aconsejaban a sus proveedores el no incurrir en este tipo de transacciones ya que eran demasiado costosas para sus servidores que albergan tantas y tan heterogéneas aplicaciones. No estoy muy seguro de lo que hay de cierto en esto, pero puede que tenga sentido :)
comments
0 Respuestas a "Tuneando transacciones con Spring"Publicar un comentario