简体   繁体   English

预加载番石榴缓存的值

[英]Pre-load values for a Guava Cache

I have a requirement where we are loading static data from a database for use in a Java application. 我有一个要求,我们从数据库加载静态数据以便在Java应用程序中使用。 Any caching mechanism should have the following functionality: 任何缓存机制都应具有以下功能:

  • Load all static data from the database (once loaded, this data will not change) 从数据库加载所有静态数据(加载后,此数据不会更改)
  • Load new data from the database (data present in the database at start-up will not change but it is possible to add new data) 从数据库加载新数据(启动时数据库中的数据不会改变,但可以添加新数据)

Lazy loading of all the data isn't an option as the application will be deployed to multiple geographical locations and will have to communicate with a single database. 由于应用程序将部署到多个地理位置并且必须与单个数据库通信,因此不能延迟加载所有数据。 Lazy loading the data will make the first request for a specific element too slow where the application is in a different region to the database. 延迟加载数据将使应用程序位于数据库的不同区域中对特定元素的第一个请求太慢。

I have been using the MapMaker API in Guava with success but we are now upgrading to the latest release and I can't seem to find the same functionality in the CacheBuilder API; 我一直在Guava中使用MapMaker API成功,但我们现在正在升级到最新版本,我似乎无法在CacheBuilder API中找到相同的功能; I can't seem to find a clean way of loading all data at start-up. 我似乎无法找到一种在启动时加载所有数据的简洁方法。

One way would be to load all keys from the database and load those through the Cache individually. 一种方法是从数据库加载所有密钥并单独通过缓存加载它们。 This would work but would result in N+1 calls to the database, which isn't quite the efficient solution I'm looking for. 这可以工作,但会导致对数据库的N + 1调用,这不是我正在寻找的有效解决方案。

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

Or the other solution is to use a ConcurrentHashMap implementation and handle all of the threads and missing entries myself? 或者另一个解决方案是使用ConcurrentHashMap实现并自己处理所有线程和缺少的条目? I'm not keen on doing this as the MapMaker and CacheBuilder APIs provide the key-based thread locking for free without having to provide extra testing. 我并不热衷于这样做,因为MapMaker和CacheBuilder API免费提供基于密钥的线程锁定,而无需提供额外的测试。 I'm also pretty sure the MapMaker/CacheBuilder implementations will have some efficiencies that I don't know about/haven't got time to investigate. 我也很确定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();
    } 
}

Can anyone think of a better solution to my two requirements? 谁能想到更好的解决方案来满足我的两个要求?


Feature Request 功能要求

I don't think pre-loading a cache is an uncommon requirement, so it would be nice if the CacheBuilder provided a configuration option to pre-load the cache. 我不认为预加载缓存是一种不常见的要求,因此如果CacheBuilder提供了一个预加载缓存的配置选项,那就太好了。 I think providing an Interface (much like CacheLoader) which will populate the cache at start-up would be an ideal solution, such as: 我认为提供一个接口(很像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);
    }

});

This implementation would allow the Cache to be pre-populated with all relevant Element objects, whilst keeping the underlying CustomConcurrentHashMap non-visible to the outside world. 此实现将允许使用所有相关的Element对象预先填充Cache,同时保持底层CustomConcurrentHashMap对外部世界不可见。

In the short-term I would just use Cache.asMap().putAll(Map<K, V>) . 在短期内我会使用Cache.asMap().putAll(Map<K, V>)

Once Guava 11.0 is released you can use Cache.getAll(Iterable<K>) , which will issue a single bulk request for all absent elements. 一旦发布了Guava 11.0,您就可以使用Cache.getAll(Iterable<K>) ,它将为所有缺席元素发出单个批量请求。

I'd load all static data from the DB, and store it in the Cache using cache.asMap().put(key, value) ([Guava 10.0.1 allows write operations on the Cache.asMap() view][1]). 我将从DB加载所有静态数据,并使用cache.asMap().put(key, value)将其存储在Cache中cache.asMap().put(key, value) ([Guava 10.0.1允许在Cache.asMap()视图上执行写操作] [1 ])。

Of course, this static data might get evicted, if your cache is configured to evict entries... 当然,如果您的缓存配置为逐出条目,这些静态数据可能会被驱逐......

The CachePopulator idea is interesting. CachePopulator的想法很有趣。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM