expireafterwrite java caching guava

java - guava expireafterwrite



Valores de precarga para un caché de guayaba (2)

A corto plazo solo usaría Cache.asMap().putAll(Map<K, V>) .

Una vez que se libera Guava 11.0, puede usar Cache.getAll(Iterable<K>) , que emitirá una solicitud masiva única para todos los elementos ausentes.

Tengo un requisito en el que estamos cargando datos estáticos de una base de datos para usar en una aplicación Java. Cualquier mecanismo de almacenamiento en caché debe tener la siguiente funcionalidad:

  • Cargue todos los datos estáticos de la base de datos (una vez cargados, estos datos no cambiarán)
  • Cargar nuevos datos de la base de datos (los datos presentes en la base de datos al inicio no cambiarán, pero es posible agregar nuevos datos)

La carga lenta de todos los datos no es una opción, ya que la aplicación se implementará en varias ubicaciones geográficas y tendrá que comunicarse con una sola base de datos. La carga lenta de los datos hará que la primera solicitud de un elemento específico sea demasiado lenta cuando la aplicación se encuentra en una región diferente a la base de datos.

He estado utilizando la API de MapMaker en Guava con éxito, pero ahora estamos actualizando a la última versión y parece que no puedo encontrar la misma funcionalidad en la API de CacheBuilder. Parece que no puedo encontrar una manera limpia de cargar todos los datos en el inicio.

Una forma sería cargar todas las claves de la base de datos y cargarlas a través del Caché individualmente. Esto funcionaría, pero daría como resultado llamadas N + 1 a la base de datos, que no es la solución eficiente que estoy buscando.

public void loadData(){ List<String> keys = getAllKeys(); for(String s : keys) cache.get(s); }

¿O la otra solución es usar una implementación ConcurrentHashMap y manejar todos los subprocesos y las entradas que faltan? No estoy interesado en hacer esto, ya que las API de MapMaker y CacheBuilder proporcionan el bloqueo de subprocesos basado en clave de forma gratuita sin tener que proporcionar pruebas adicionales. También estoy bastante seguro de que las implementaciones de MapMaker / CacheBuilder tendrán algunas eficiencias que no conozco / no tengo tiempo para investigar.

public Element get(String key){ Lock lock = getObjectLock(key); lock.lock(); try{ Element ret = map.get(key) if(ret == null){ ret = getElement(key); // database call map.put(key, e); } return ret; }finally { lock.unlock(); } }

¿Alguien puede pensar en una mejor solución para mis dos requisitos?

Solicitud de función

No creo que precargar un caché sea un requisito poco común, por lo que sería bueno que CacheBuilder proporcionara una opción de configuración para precargar el caché. Creo que proporcionar una Interfaz (como CacheLoader) que llenará el caché en el inicio sería una solución ideal, como:

CacheBuilder.newBuilder().populate(new CachePopulator<String, Element>(){ @Override public Map<String, Element> populate() throws Exception { return getAllElements(); } }).build(new CacheLoader<String, Element>(){ @Override public Element load(String key) throws Exception { return getElement(key); } });

Esta implementación permitiría que la memoria caché se rellene previamente con todos los objetos del Elemento relevantes, al tiempo que mantiene el CustomConcurrentHashMap subyacente no visible para el mundo exterior.


cache.asMap().put(key, value) todos los datos estáticos de la base de datos y los almacenaría en el caché usando cache.asMap().put(key, value) ([Guava 10.0.1 permite operaciones de escritura en la vista Cache.asMap ()] [1 ]).

Por supuesto, estos datos estáticos pueden ser desalojados, si su caché está configurado para desalojar entradas ...

La idea de CachePopulator es interesante.