Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中实现周期性刷新缓存_Java_Caching_Bulkinsert_Bulk - Fatal编程技术网

在Java中实现周期性刷新缓存

在Java中实现周期性刷新缓存,java,caching,bulkinsert,bulk,Java,Caching,Bulkinsert,Bulk,我的用例是在持久数据库中存储的数据上维护内存缓存 我使用这些数据在UI上填充条目列表/映射。在任何给定的时间,UI上显示的数据都应该尽可能地更新(这可以通过缓存的刷新频率来实现) 常规缓存实现与此特定缓存之间的主要区别在于,它需要定期对所有元素进行批量刷新,因此与LRU类型的缓存非常不同 我需要用Java来实现这个功能,如果有任何现有的框架可以用来构建这个功能,那就太好了 我已经探索过Google Guava缓存库,但它更适合按条目刷新,而不是批量刷新。没有简单的API可以刷新整个缓存 我们将非

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

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

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

我需要用Java来实现这个功能,如果有任何现有的框架可以用来构建这个功能,那就太好了

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

我们将非常感谢您的帮助


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

只要继承这个类,并实现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;
    }

}
import org.apache.log4j.Logger;
导入java.util.List;
导入java.util.concurrent.Semaphore;
公共抽象类可更新
{
受保护的易失性长lastRefreshed=0;
私有最终整型刷新\u频率\u毫秒=300000;//5分钟
私有线程更新读取;
私有最终信号量updateInProgress=新信号量(1);
受保护的静态最终记录器log=Logger.getLogger(可更新的.class);
公共文件
{
尝试
{
updateInProgress.acquire();
}
捕捉(中断异常e)
{
日志警告(“强制刷新中断”);
}
尝试
{
loadAllData();
}
捕获(例外e)
{
log.error(“从DB更新数据时出现异常”,e);
}
最后
{
updateInProgress.release();
}
}
受保护的void checkRefresh()
{
如果(lastRefreshed+刷新频率\u毫秒
是一个功能非常全面的java缓存库。我想他们会有适合你的东西

为了对缓存进行增量重新加载(这在大多数缓存上都有效),只需迭代当前加载的条目并强制刷新它们。(您可以在后台计划程序上运行此任务)


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

必须检查的一点是,是否需要定期刷新?一旦从缓存中提取数据,就可以应用刷新逻辑,这样就不需要进行任何异步刷新,也不需要维护缓存的任何旧副本。这是刷新缓存数据的最简单和最好的方法,因为它不涉及任何额外的开销

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

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

谢谢你的回答。何时调用checkRefresh()函数?如果我理解正确,这将需要一个连续运行的进程来定期使用checkRefresh进行轮询。我期待着一个更干净的实现,在这个实现中,我可以用缓存加载程序插入一个新的缓存。在类中实现的每个get操作中都应该调用CheckRefresh。例如:public Data get(){checkRefresh();//return Data;}但是当更新线程被触发时,如果它像cron一样进行并且已经预取了数据,那么这种情况就不会出现,这将影响数据检索的延迟。在我们的例子中,我们认为数据可能有点过时。如果从DB同步获取数据,则可以确保数据永远不会过时,但这样所有请求都必须等待数据被获取。这对我们来说是不可接受的,因为我们的系统的延迟非常低,我们不能停止所有的请求,直到获取数据。我同意我们同意数据过时。我想说的是