Осуществляет периодическое обновление кэша в Java

мой вариант использования-поддерживать кэш в памяти над данными, хранящимися в постоянной БД.

Я использую данные для заполнения списка / карты записей в пользовательском интерфейсе. В любой момент времени данные, отображаемые в пользовательском интерфейсе, должны быть максимально обновлены (это можно сделать по частоте обновления кэша).

основное различие между обычной реализацией кэша и этим конкретным кэшем заключается в том, что ему требуется массовое обновление всех элементов через регулярные промежутки времени и, следовательно, сильно отличается от кэша типа LRU.

Мне нужно сделать эту реализацию в Java, и будет здорово, если есть какие-либо существующие фреймворки, которые могут быть использованы для их создания.

Я изучил библиотеку кэша Google Guava, но она больше подходит для обновления каждой записи, а не для массового обновления. Нет простых API, которые делают обновление для всего кэша.

любая помощь будет высоко оцененный.

кроме того, если можно постепенно выполнить обновление, это будет здорово, потому что единственное ограничение, которое возникает при обновлении всего кэша, заключается в том, что если кэш очень большой по размеру, то куча памяти должна быть по крайней мере вдвое больше размера кэша, чтобы загрузить новые записи и заменить старую карту новой. Если кэш инкрементный или есть фрагментированное обновление (Обновление в равных размерах), это будет здорово.

3 ответов


EHCache - довольно полнофункциональная библиотека кэширования java. я бы предположил, что у них есть что-то, что сработает для вас.

чтобы выполнить инкрементную перезагрузку кэша (который будет работать на большинстве любого кэша), просто повторите загруженные в настоящее время записи и принудительно обновите их. (вы можете запустить эту задачу в фоновом планировщике).

в качестве альтернативы принудительной перезагрузке всего кэша EHCache имеет возможность указать "time-to-live" для записи, поэтому записи будут автоматически перезагружены, если они слишком устаревшие.


просто наследовать этот класс и реализовать loadDataFromDB и updateData, как вы хотите получить инкрементные обновления

import org.apache.log4j.Logger;
import java.util.List;
import java.util.concurrent.Semaphore;


public abstract class Updatable<T>
{
    protected volatile long lastRefreshed = 0;
    private final int REFRESH_FREQUENCY_MILLISECONDS = 300000; // 5 minutes
    private Thread updateThread;
    private final Semaphore updateInProgress = new Semaphore(1);

    protected static final Logger log = Logger.getLogger(Updatable.class);

    public void forceRefresh()
    {
        try
        {
            updateInProgress.acquire();
        }
        catch (InterruptedException e)
        {
            log.warn("forceRefresh Interrupted");
        }

        try
        {
            loadAllData();
        }
        catch (Exception e)
        {
            log.error("Exception while updating data from DB", e);
        }
        finally
            {
            updateInProgress.release();
        }

    }

    protected void checkRefresh()
    {
        if (lastRefreshed + REFRESH_FREQUENCY_MILLISECONDS <     System.currentTimeMillis())
            startUpdateThread();
    }

    private void startUpdateThread()
    {
        if (updateInProgress.tryAcquire())
        {
            updateThread = new Thread(new Runnable()
            {
                public void run()
                {
                    try
                    {
                        loadAllData();
                    }
                    catch (Exception e)
                    {
                        log.error("Exception while updating data from DB", e);
                    }
                    finally
                    {
                        updateInProgress.release();
                    }
                }
            });

            updateThread.start();
        }
    }

    /**
     * implement this function to load the data from DB
     *
     * @return
     */
    protected abstract List<T> loadFromDB();

    /**
     * Implement this function to hotswap the data in memory after it was loaded from DB
     *
     * @param data
     */
    protected abstract void updateData(List<T> data);

    private void loadAllData()
    {
        List<T> l = loadFromDB();
        updateData(l);
        lastRefreshed = System.currentTimeMillis();
    }

    public void invalidateCache()
    {
         lastRefreshed = 0;
    }

}

одна вещь,которая должна быть проверена, - это периодическое обновление? Вы можете применить логику обновления после извлечения данных из кэша, это устранит необходимость в асинхронном обновлении и устранит необходимость поддержания любых старых копий кэша. Это IMO-самый простой и лучший способ обновления данных кэша, поскольку он не включает никаких дополнительных накладных расходов.

 T getData(){
      // check if the last access time + refresh interval >= currenttime if so then    refresh cache
     // return data
    }

это гарантирует, что данные будут обновлены на основе обновления интервал и он не нуждается в асинхронном обновлении .