预加载番石榴缓存的值 [英] Pre-load values for a Guava Cache

查看:119
本文介绍了预加载番石榴缓存的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a requirement where we are loading static data from a database for use in a Java application. Any caching mechanism should have the following functionality:


  • 从数据库加载所有静态数据(加载后,此数据不会更改)

  • 从数据库加载新数据(启动时数据库中的数据不会改变,但可以添加新数据)

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

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.

我一直在使用MapMaker API番石榴成功但我们现在升级到最新版本,我似乎无法在CacheBuilder API中找到相同的功能;我似乎无法找到一种在启动时加载所有数据的简洁方法。

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; I can't seem to find a clean way of loading all data at start-up.

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

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.

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

或者其他解决方案是使用ConcurrentHashMap实现并处理所有线程我自己缺少参赛作品?我并不热衷于这样做,因为MapMaker和CacheBuilder API免费提供基于密钥的线程锁定,而无需提供额外的测试。我也很确定MapMaker / CacheBuilder实现会有一些我不知道/没有时间调查的效率。

Or the other solution is to use a ConcurrentHashMap implementation and handle all of the threads and missing entries myself? 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. 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.

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

我不认为预加载缓存是一种不常见的要求,因此如果CacheBuilder提供了一个预加载缓存的配置选项,那就太好了。我认为提供一个接口(很像CacheLoader),它将在启动时填充缓存,这将是一个理想的解决方案,例如:

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. I think providing an Interface (much like CacheLoader) which will populate the cache at start-up would be an ideal solution, such as:

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);
    }

});

此实现允许使用所有相关的Element对象预先填充Cache,同时保留底层CustomConcurrentHashMap对外界不可见。

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.

推荐答案

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

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

Once Guava 11.0 is released you can use Cache.getAll(Iterable<K>), which will issue a single bulk request for all absent elements.

这篇关于预加载番石榴缓存的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆