(上下文)我需要构建一个缓存,从数据库加载信息并使其可供应用程序使用。此数据不会在此应用程序中更改,并且会被大量线程大量使用(检索)。数据可能(很少)从另一个应用程序更改。每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加载两次相同的条目?
答案 0 :(得分:1)
缓存中的Ehcache 3 模式将在加载程序执行时阻止对给定键的所有访问。这也表明装载机性能很重要。
在您的方案中,这意味着单个请求将转到数据库,当条目在缓存中时,在第一个线程完成加载后,第二个线程将能够从缓存中读取它。
请注意,此系统与线程安全无关,您的加载器对于不同的密钥仍必须是线程安全的,但关于有效的资源使用。它假定从DB加载比缓存命中慢得多。