我的用例是在存储在持久数据库中的数据上维护内存缓存。
我使用数据填充UI上的条目列表/地图。在任何给定时间,UI上显示的数据应尽可能更新(这可以通过缓存的刷新频率来完成)。
常规缓存实现与此特定缓存之间的主要区别在于,它需要定期刷新所有元素,因此与LRU类缓存非常不同。
我需要在Java中实现这个实现,如果有任何现有的框架可以用来构建它们,那将会很棒。
我已经探索过Google Guava缓存库,但它更适合每次刷新而不是批量刷新。没有简单的API可以对整个缓存进行刷新。
任何帮助都将受到高度赞赏。
此外,如果可以逐步进行刷新,那么它应该很棒,因为刷新整个缓存时出现的唯一限制是,如果缓存的大小非常大,那么内存堆应至少是两倍。缓存的大小,以便加载新条目并用新的映射替换旧映射。如果缓存是增量的,或者存在分块刷新(刷新大小相同),那就太棒了。
答案 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
}
这将确保根据刷新间隔刷新数据,并且不需要任何异步刷新。