9

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

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

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

我需要在 Java 中完成这个实现,如果有任何现有的框架可以用来围绕它们构建它,那就太好了。

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

任何帮助将不胜感激。

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

4

3 回答 3

3

EHCache是一个功能非常齐全的 java 缓存库。我想他们有一些对你有用的东西。

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

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

于 2012-10-05T14:05:08.817 回答
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;
    }

}
于 2012-10-05T13:22:34.720 回答
0

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

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

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

于 2016-07-27T06:11:39.797 回答