使用Spring / EHCache加载时刷新缓存 [英] Refreshing Caches while under load with Spring/EHCache

查看:479
本文介绍了使用Spring / EHCache加载时刷新缓存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a caching issue on a Spring multi-threaded web service with a database backend and EHCache-based caching. The service has many clients all requesting the same object again and again, with dozens of requests per seconds. There is only a couple of objects that are requested that frequently, with a large number of other objects being requested infrequently. The objects can change every couple of minutes, so the cache's TTL is set to a minute. Loading an object from the database is slow and takes at least several seconds.

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

At first I used a naive implementation to get the object:


  1. 检查对象是否在缓存中。

  2. 如果是,请从缓存中返回。

  3. 如果没有,请从数据库加载它,将其放入缓存并返回。

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

This was working well when initially testing it locally. But performance testing on a faster server showed some pretty bad load spikes every time one of the more frequently requested objects expires in the cache. When this happens, for the next 10 seconds all requests for that object would result in database loads, until the first thread finished the database load and put the new object into the cache. The result was a short but very high load on the database, and a lot of users who need to wait for the request to finish.

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

My current implementation improves the database load by tracking whether which object are currently being loaded:


  1. 检查对象是否被缓存。

  2. 如果是,请从缓存中返回。

  3. 如果没有,检查对象当前是否正在加载。

  4. 如果是,请等待另一个线程的加载完成,从缓存中获取新对象并返回它。

  5. 如果不是,将对象放入加载对象列表,完成后将其放入缓存并返回。

  1. Check whether the object is cached.
  2. If yes, return it from the cache.
  3. If not, check whether the object is currently being loaded.
  4. If yes, wait for the other thread's load to complete, get the new object from the cache and return it.
  5. If no, put the object into the list of loading objects, put it into the cache when finished and return it.

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

With this implementation, even when the object expires, there is only one database operation. And, because of the lower database load, it will also finish sooner. But it still means that all users who request the object during the object load need to wait.

我真正想要的是只有第一个线程等待数据库加载,以及所有其他人只是在加载对象时返回'过期'对象。对于我来说,响应时间比对象太旧的事实更重要。

What I would really want is that only the first thread waits for the database load, and all others just return the 'expired' object while the object is being loaded. Response time is more important for me than the fact that the object is a few seconds too old.

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

Alternatively I could refresh the cache asynchronously when I notice that an object will expire in a few seconds. That's closer to EHCache's single TTL model and would mean that no one needs to wait for the database load

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

My real question is: before I re-invent the wheel, is there any existing framework that already implements something like this (in a Spring/EHCache environment)? Or maybe support for this already exists somewhere in Spring/EHCache and I just can't find the right option?

推荐答案

两个Ehcache提供的结构可以帮助你:

There are two Ehcache provided constructs that could help you:


  1. 提前刷新

  2. 预定刷新

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

Both require you to change the way you interact with your cache as they require a CacheLoader to be configured.

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

Unfortunately, I can't find online documentation that shows example for the second option. It allows to refresh cache entries using Quartz to schedule it. It can also refresh only a subset of the keys, based on a key generator. Have a look at classes in package net.sf.ehcache.constructs.scheduledrefresh

这篇关于使用Spring / EHCache加载时刷新缓存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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