2012-04-14 8 views
7

Dos cosas que realmente me gustan de CacheLoader de Guava 11 (¡gracias, Google!) Son loadAll(), que me permite cargar varias claves a la vez, y volver a cargar(), me permite volver a cargar una clave de forma asíncrona cuando está "obsoleta" pero existe un valor anterior. Tengo curiosidad sobre cómo juegan juntos, ya que reload() funciona con una sola clave.Google Guava's CacheLoader loadAll() vs reload() semántica

Concretamente, se extiende el ejemplo de CachesExplained:

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder() 
    .maximumSize(1000) 
    .refreshAfterWrite(1, TimeUnit.MINUTES) 
    .build(
     new CacheLoader<Key, Graph>() { 
     public Graph load(Key key) { // no checked exception 
      return getGraphFromDatabase(key); 
     } 

     public Map<Key, Graph> loadAll(Iterable<? extends K> keys) { 
      return getAllGraphsFromDatabase(keys); 
     } 

     public ListenableFuture<Graph> reload(final Key key, Graph prevGraph) { 
      if (neverNeedsRefresh(key)) { 
      return Futures.immediateFuture(prevGraph); 
      } else { 
      // asynchronous! 
      return ListenableFutureTask.create(new Callable<Graph>() { 
       public Graph call() { 
       return getGraphFromDatabase(key); 
       } 
      }); 
      } 
     } 
     }); 

... donde "getAllGraphsFromDatabase()" hace una consulta de base de datos agregada en lugar de longitud (teclas) consultas individuales.

¿Cómo se combinan estos dos componentes de un dispositivo LoadingCache? Si algunas claves en mi solicitud para getAll() no están presentes en la memoria caché, se cargan como un grupo con loadAll(), pero si algunas necesitan actualizarse, ¿se vuelven a cargar individualmente con load()? Si es así, ¿hay planes para admitir un reloadAll()?

+0

[Cache.getAll no puede desencadenar actualización # 971] (https://github.com/google/guava/issues/971) todavía está abierto para votar – Vadzim

Respuesta

13

Así funciona la actualización.

refrescante en una entrada de caché pueden activarse de dos maneras:

  1. explícitamente, con cache.refresh(key).
  2. Implícitamente, si la memoria caché está configurada con refreshAfterWrite y la entrada es consultada después de la cantidad de tiempo especificada después de su escritura.

Si se consulta una entrada que es elegible para la recarga, se devuelve el valor anterior y se desencadena una actualización (posiblemente asíncrona). La memoria caché continuará devolviendo el valor anterior de la clave mientras la actualización está en progreso. (Así que si algunas de las claves en una solicitud getAll son elegibles para la actualización, serán devueltos a sus antiguos valores, pero los valores relativos a las llaves estarán (posiblemente de forma asíncrona) vuelve a cargar.)

El predeterminado implementación de CacheLoader.reload(key, oldValue) sólo devuelve Futures.immediateFuture(load(key)) , que (sincrónicamente) vuelve a calcular el valor. Se recomiendan implementaciones asincrónicas más sofisticadas si espera realizar actualizaciones de caché.

No creo que estemos dispuestos a proporcionar reloadAll por el momento. Sospecho que es posible, pero las cosas ya son lo suficientemente complicadas, y creo que estamos dispuestos a esperar hasta que veamos una demanda específica para tal cosa.

+0

Sabía que ustedes están por todo el Desbordamiento, que es por qué Pensé que preguntaría aquí. ¡Gracias! Entonces, si realizo una llamada getAll(), puedo tener potencialmente tres tipos de claves. Aquellos que están presentes (y frescos) en el caché, los que no están en el caché y los que están presentes (y listos para una actualización). Los que están presentes se devuelven desde la memoria caché, los que no están presentes se extraen a través de mi función loadAll() y los que están presentes en la memoria caché pero están listos para actualizarse devuelven los valores anteriores pero luego se vuelven a cargar uno por uno ¿asincrónicamente? ¿Es eso correcto? – spitzanator

+0

Bueno, "uno por uno" y "asincrónico" no sería la terminología que uso, pero estoy bastante seguro de que lo has hecho bien. (Aunque los elementos se actualizarán individualmente, sus actualizaciones serán _concurrentes_.) –

+0

¡Gracias! ¿Hay alguna manera de controlar cuántas actualizaciones simultáneas se producen, por lo que no doy mi base de datos?Si le pido a mi caché 100 claves, quiero evitar hacer 90 solicitudes paralelas de bases de datos individuales para actualizar los valores obsoletos cuando una única consulta para recuperarlos sea suficiente. – spitzanator