在Java中实现周期性刷新缓存
我的用例是在持久数据库中存储的数据上维护内存缓存 我使用这些数据在UI上填充条目列表/映射。在任何给定的时间,UI上显示的数据都应该尽可能地更新(这可以通过缓存的刷新频率来实现) 常规缓存实现与此特定缓存之间的主要区别在于,它需要定期对所有元素进行批量刷新,因此与LRU类型的缓存非常不同 我需要用Java来实现这个功能,如果有任何现有的框架可以用来构建这个功能,那就太好了 我已经探索过Google Guava缓存库,但它更适合按条目刷新,而不是批量刷新。没有简单的API可以刷新整个缓存 我们将非常感谢您的帮助在Java中实现周期性刷新缓存,java,caching,bulkinsert,bulk,Java,Caching,Bulkinsert,Bulk,我的用例是在持久数据库中存储的数据上维护内存缓存 我使用这些数据在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同步获取数据,则可以确保数据永远不会过时,但这样所有请求都必须等待数据被获取。这对我们来说是不可接受的,因为我们的系统的延迟非常低,我们不能停止所有的请求,直到获取数据。我同意我们同意数据过时。我想说的是