使用Spring/EHCache加载时刷新缓存

Tim*_*sen 2 java spring multithreading caching ehcache

我在具有数据库后端和基于EHCache的缓存的Spring多线程Web服务上有一个缓存问题.该服务有许多客户端一次又一次地请求相同的对象,每秒有几十个请求.经常请求的对象只有几个,并且不经常请求大量其他对象.对象每隔几分钟就可以更改一次,因此缓存的TTL设置为一分钟.从数据库加载对象很慢并且至少需要几秒钟.

起初我使用了一个天真的实现来获取对象:

  1. 检查对象是否在缓存中.
  2. 如果是,请从缓存中返回.
  3. 如果没有,从数据库加载它,将其放入缓存并返回它.

这在最初在本地测试时运行良好.但是,每当一个更频繁请求的对象在缓存中到期时,在更快的服务器上进行性能测试就会显示出一些非常糟糕的负载峰值.发生这种情况时,在接下来的10秒内,对该对象的所有请求都将导致数据库加载,直到第一个线程完成数据库加载并将新对象放入缓存.结果是数据库上的负载很短但非常高,并且许多用户需要等待请求完成.

我当前的实现通过跟踪当前正在加载哪个对象来改进数据库负载:

  1. 检查对象是否被缓存.
  2. 如果是,请从缓存中返回.
  3. 如果没有,请检查当前是否正在加载对象.
  4. 如果是,请等待另一个线程的加载完成,从缓存中获取新对象并将其返回.
  5. 如果不是,则将对象放入加载对象列表中,完成后将其放入缓存中并返回.

通过此实现,即使对象到期,也只有一个数据库操作.并且,由于较低的数据库负载,它也将更快完成.但它仍然意味着在对象加载期间请求对象的所有用户都需要等待.

我真正想要的是只有第一个线程等待数据库加载,而所有其他线程只是在加载对象时返回'过期'对象.对于我来说,响应时间比对象太老了几秒钟更重要.

或者,当我注意到对象将在几秒钟内过期时,我可以异步刷新缓存.这更接近EHCache的单个TTL模型,并且意味着没有人需要等待数据库负载

我真正的问题是:在我重新发明轮子之前,是否有任何现有的框架已经实现了这样的东西(在Spring/EHCache环境中)?或者也许在Spring/EHCache中存在对此的支持,我找不到合适的选项?

Lou*_*met 5

有两个Ehcache提供的构造可以帮助您:

  1. 提前刷新
  2. 预定刷新

两者都要求您更改与缓存交互的方式,因为它们需要CacheLoader进行配置.

不幸的是,我找不到显示第二个选项示例的在线文档.它允许使用Quartz刷新缓存条目来安排它.它还可以基于密钥生成器仅刷新密钥的子集.看一下课程中的课程net.sf.ehcache.constructs.scheduledrefresh