如果一个请求的id 不存在,Cache 不会得到它,请求将通过数据库进行查询。
不存在的 id 请求将全部命中 Database,如果这是攻击,缓存将无法保护 Database。
很快数据库就关闭了。
那么我能做些什么来防止这种类型的攻击呢?
PS 数据库数据太多。如果一个 id 只访问一次,Null Object Cache将不起作用。
如果一个请求的id 不存在,Cache 不会得到它,请求将通过数据库进行查询。
不存在的 id 请求将全部命中 Database,如果这是攻击,缓存将无法保护 Database。
很快数据库就关闭了。
那么我能做些什么来防止这种类型的攻击呢?
PS 数据库数据太多。如果一个 id 只访问一次,Null Object Cache将不起作用。
您可以缓存一个 Optional,如果响应为空,您将在第一个请求中保存 Optional.absent()。只要数据库中存在关联的 Id,就必须使该缓存的 Optional 实体无效,或者如果您在不断增长的缓存中遇到内存问题,则必须尽快使该实体无效。
我喜欢 guava 的 Cache 和 Optional 类,因为我认为它们解决了大多数可能的问题,我将在我的示例中使用它们:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import com.google.common.base.Optional;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
public class OptionalCacheUsage {
private static final Cache<Id, Optional<Entity>> cache = CacheBuilder.newBuilder()
.softValues()
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();
private static final Database db = Databases.getDatabase();
Entity findEntity(final Id requestedId) throws ExecutionException, EntityNotFoundException {
final Optional<Entity> optionalEntity = cache.get(requestedId, new Callable<Optional<Entity>>() {
@Override public Optional<Entity> call() throws Exception {
return Optional.fromNullable(db.getById(requestedId));
}});
if (optionalEntity.isPresent()) {
return optionalEntity.get();
} else {
throw new EntityNotFoundException();
}
}
Id saveEntity(final Entity newEntity) {
final Id savedId = db.save(newEntity);
cache.invalidate(savedId);
return savedId;
}
}