Caché distribuida vs replicada en clústers de Jboss EAP 6 +

A la hora de montar un clúster en alta disponibilidad con Jboss tendremos que plantearnos qué tipo de caché vamos a utilizar para garantizar la alta disponibilidad.

De la gestión de caché se encarga Infinispan desde la versión de Jboss EAP 6 de Red Hat y la AS7 / Wildfly que son versiones comunitarias de Jboss. Infinispan se encuentra embebido en el servidor de aplicaciones como un subsistema más en los perfiles de alta disponibilidad (full-ha y ha)

Por ejemplo, en un fichero standalone-full-ha.xml encontraremos en primer lugar el módulo cargado:

...
<extension module="org.jboss.as.clustering.infinispan"/>
...

Y la correspondiente sección de configuración del subsistema:

...
<subsystem xmlns="urn:jboss:domain:infinispan:1.5">                                                                                                               
    <cache-container name="singleton" aliases="cluster ha-partition" default-cache="default">
        <transport lock-timeout="60000"/>
        <replicated-cache name="default" mode="SYNC" batching="true">
            <locking isolation="REPEATABLE_READ"/>
        </replicated-cache>
    </cache-container>
    <cache-container name="web" aliases="standard-session-cache" default-cache="repl" module="org.jboss.as.clustering.web.infinispan">
        <transport lock-timeout="60000"/>
        <replicated-cache name="repl" mode="ASYNC" batching="true">
...

Tipos de caché para entornos de alta disponibilidad

Para los entornos en clúster que son los que estamos tratando en el artículo, tendremos dos tipos de caché con los que Infinispan garantiza la alta disponibilidad:

  • Modo réplica: todos los nodos del clúster contienen la misma caché. El proceso de sincronización de caché es costoso en términos de recursos. A mayor nº de nodos en el clúster, mayor coste en mantener la caché replicada entre los mismos, y aún si nos encontramos en un entorno de alta concurrencia.
  • Modo distribuida: un determinado nº de nodos (por defecto 2) guardan las réplicas de caché del clúster. Es una opción que nos da mayor escalabilidad y por tanto recomendada en clústers de gran tamaño (+ de 8 nodos)

Cada sección cache-container tiene un modo de caché asociado que se especifica mediante el atributo default-cache. Así, para las sesiones web tenemos que el modo utilizado por defecto es default-cache="repl", es decir, en modo réplica:

<cache-container name="web" aliases="standard-session-cache" default-cache="repl" module="org.jboss.as.clustering.web.infinispan">
    <transport lock-timeout="60000"/>
    <replicated-cache name="repl" mode="ASYNC" batching="true">
        <file-store/>
    </replicated-cache>
    <replicated-cache name="sso" mode="SYNC" batching="true"/>
    <distributed-cache name="dist" mode="ASYNC" batching="true" l1-lifespan="0">
        <file-store/>
    </distributed-cache>
</cache-container>

Y para los EJB también se utiliza por defecto modo réplica:

<cache-container name="ejb" aliases="sfsb sfsb-cache" default-cache="repl" module="org.jboss.as.clustering.ejb3.infinispan">
    <transport lock-timeout="60000"/>
    <replicated-cache name="repl" mode="ASYNC" batching="true">
        <eviction strategy="LRU" max-entries="10000"/>
        <file-store/>
    </replicated-cache>
    <!--
      ~  Clustered cache used internally by EJB subsytem for managing the client-mapping(s) of
      ~                 the socketbinding referenced by the EJB remoting connector 
      -->
    <replicated-cache name="remote-connector-client-mappings" mode="SYNC" batching="true"/>
    <distributed-cache name="dist" mode="ASYNC" batching="true" l1-lifespan="0">
        <eviction strategy="LRU" max-entries="10000"/>
        <file-store/>
    </distributed-cache>
</cache-container>

Como vemos, cada cache-container tiene configurado a su manera un modo de caché distribuida y replicada. Después, como veíamos al principio, aplica el tipo de caché que ese container va a utilizar por defecto con el atributo default-cache. El modo de caché de un contenedor puede cambiarse por tanto modificando el atributo default-cache.

En el caso de la caché distribuida, por defecto 2 nodos en el clúster son elegidos para mantener las réplicas de caché. Podemos modificar este comportamiento con el atributo owners:

    <distributed-cache name="dist" owners="4" mode="ASYNC" batching="true" l1-lifespan="0">
        <eviction strategy="LRU" max-entries="10000"/>
        <file-store/>
    </distributed-cache>

Siempre teniendo en cuenta que a mayor nº de owners, mayor coste en mantener la caché sincronizada entre los nodos que han sido elegidos para tal fin.

Habrías podido ver también el atributo mode dentro de la configuración de cada tipo de caché. El valor de dicho atributo puede ser:

  • ASYNC: si buscamos velocidad esta será la mejor opción, aunque sacrificaremos consistencia de datos. Si utilizamos sticky sessions para las sesiones web es viable ya que la afinidad de sesión hará que los datos se sirvan siempre que se pueda en el mismo nodo.
  • SYNC: si buscamos un alto nivel de consistencia en los datos de caché utilizaremos este modo. Si no tenemos sticky session para sesiones web sería recomendable utilizar caché en modo sync para que el acceso a cualquiera de los nodos del clúster presente datos consistentes.

Como vemos, el subsistema Infinispan nos permite granularizar de una forma precisa el comportamiento de la caché en nuestro clúster para conseguir el mayor rendimiento posible. A su vez tendremos que saber elegir qué opciones son las más adecuadas según la arquitectura en la que nos encontremos y recursos disponibles.