在Java中实现定期刷新的Cache

时间:2012-10-05 13:17:01

标签: java caching bulkinsert bulk

我的用例是在存储在持久数据库中的数据上维护内存缓存。

我使用数据填充UI上的条目列表/地图。在任何给定时间,UI上显示的数据应尽可能更新(这可以通过缓存的刷新频率来完成)。

常规缓存实现与此特定缓存之间的主要区别在于,它需要定期刷新所有元素,因此与LRU类缓存非常不同。

我需要在Java中实现这个实现,如果有任何现有的框架可以用来构建它们,那将会很棒。

我已经探索过Google Guava缓存库,但它更适合每次刷新而不是批量刷新。没有简单的API可以对整个缓存进行刷新。

任何帮助都将受到高度赞赏。

此外,如果可以逐步进行刷新,那么它应该很棒,因为刷新整个缓存时出现的唯一限制是,如果缓存的大小非常大,那么内存堆应至少是两倍。缓存的大小,以便加载新条目并用新的映射替换旧映射。如果缓存是增量的,或者存在分块刷新(刷新大小相同),那就太棒了。

3 个答案:

答案 0 :(得分:3)

EHCache是一个功能齐全的java缓存库。我想他们会有适合你的东西。

为了对缓存进行增量重新加载(适用于大多数缓存),只需遍历当前加载的条目并强制刷新它们。 (您可以在后台调度程序上运行此任务)。

作为强制整个缓存重新加载的替代方法,EHCache能够为条目指定“生存时间”,因此如果条目过于陈旧,则会自动重新加载条目。

答案 1 :(得分:0)

只需继承此类,并实现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;
    }

}

答案 2 :(得分:0)

需要检查的一件事是需要定期刷新吗?从缓存中获取数据后,您可以应用刷新逻辑,这将消除对任何异步刷新的需要,并且无需维护任何旧的缓存副本。这个IMO是刷新缓存数据的最简单和最好的方法,因为它不涉及任何额外的开销。

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

这将确保根据刷新间隔刷新数据,并且不需要任何异步刷新。