0

(上下文)我需要构建一个从数据库加载信息并使其可供应用程序使用的缓存。此数据不会在此应用程序中更改,并且将被大量线程大量使用(检索)。数据可能(很少)从另一个应用程序更改。每1小时更新一次就足够了。猜猜 Ehcache 将是一个不错的选择,它创建一个通读缓存。

想了一些这样的缓存:

CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
        .withCache("preConfigured",
                CacheConfigurationBuilder.newCacheConfigurationBuilder(Integer.class, String.class, ResourcePoolsBuilder.heap(100))
                        .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofHours(1)))
                        .withLoaderWriter(new CacheDataProvider())).build();

cacheManager.init();

Cache<Integer, String> myCache = cacheManager.getCache("preConfigured", Integer.class, String.class);

想象一下缓存过期(1 小时后),一个线程使用键 1 请求条目,不久之后另一个线程请求相同的条目 1。当第一个线程请求条目 1 时,缓存将检查它是否已过期并询问 LoaderWriter加载条目 1。

我的问题是:当 LoaderWriter 为第一个请求加载条目 1 时,缓存是否会让第二个线程“等待”直到条目 1 被加载,或者,第二个请求是否会再次触发(几乎)同时加载条目 1。也就是说,导致同一条目从 LoaderWriter 加载两次?

4

1 回答 1

1

缓存通过模式下的 Ehcache 3将在加载程序执行时阻止对给定键的所有访问。这也表明加载器性能很重要。

在您的场景中,这意味着单个请求将进入数据库,并且当条目在缓存中时,在第一个线程完成加载后,第二个线程将能够从缓存中读取它。

请注意,此系统不是关于线程安全的,您的加载器对于不同的键仍然必须是线程安全的,而是关于有效的资源使用。它假设从数据库加载比缓存命中慢得多。

于 2018-06-06T11:36:32.233 回答