gpt4 book ai didi

java - Guava 缓存的预加载值

转载 作者:IT老高 更新时间:2023-10-28 20:35:47 25 4
gpt4 key购买 nike

我有一个要求,我们从数据库加载静态数据以用于 Java 应用程序。任何缓存机制都应具有以下功能:

  • 从数据库中加载所有静态数据(一旦加载,此数据不会改变)
  • 从数据库加载新数据(启动时数据库中的数据不会改变,但可以添加新数据)

所有数据的延迟加载不是一个选项,因为应用程序将部署到多个地理位置并且必须与单个数据库进行通信。延迟加载数据会使对特定元素的第一次请求太慢,因为应用程序与数据库位于不同的区域。

我在 Guava 中成功使用了 MapMaker API,但我们现在正在升级到最新版本,我似乎无法在 CacheBuilder API 中找到相同的功能;我似乎找不到在启动时加载所有数据的干净方法。

一种方法是从数据库中加载所有键,并通过缓存单独加载它们。这会起作用,但会导致对数据库的 N+1 次调用,这不是我正在寻找的有效解决方案。

public void loadData(){
List<String> keys = getAllKeys();
for(String s : keys)
cache.get(s);
}

或者其他解决方案是使用 ConcurrentHashMap 实现并自己处理所有线程和丢失的条目?我并不热衷于这样做,因为 MapMaker 和 CacheBuilder API 免费提供了基于 key 的线程锁定,而无需提供额外的测试。我也很确定 MapMaker/CacheBuilder 实现会有一些我不知道/没有时间研究的效率。

public Element get(String key){
Lock lock = getObjectLock(key);
lock.lock();
try{
Element ret = map.get(key)
if(ret == null){
ret = getElement(key); // database call
map.put(key, e);
}
return ret;
}finally {
lock.unlock();
}
}

谁能想到一个更好的解决方案来满足我的两个要求?


功能请求

我不认为预加载缓存是一个不常见的要求,所以如果 CacheBuilder 提供一个配置选项来预加载缓存会很好。我认为提供一个在启动时填充缓存的接口(interface)(很像 CacheLoader)将是一个理想的解决方案,例如:

CacheBuilder.newBuilder().populate(new CachePopulator<String, Element>(){

@Override
public Map<String, Element> populate() throws Exception {
return getAllElements();
}

}).build(new CacheLoader<String, Element>(){

@Override
public Element load(String key) throws Exception {
return getElement(key);
}

});

此实现将允许缓存预先填充所有相关的元素对象,同时保持底层的 CustomConcurrentHashMap 对外界不可见。

最佳答案

短期内我会使用 Cache.asMap().putAll(Map<K, V>) .

Guava 11.0 发布后,您可以使用 Cache.getAll(Iterable<K>) ,它将为所有缺失的元素发出一个批量请求。

关于java - Guava 缓存的预加载值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7915016/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com