guava缓存批量获取的一个坑
摘要
Guava Cache是Google开源的Java工具集库Guava里的一款缓存工具,一直觉得使用起来比较简单,没想到这次居然还踩了一个坑
背景
功能需求抽象出来很简单,就是将数据库的查询sthMapper.findById(Long id)的结果缓存起来。但同时还有批量请求,为了提高效率,肯定要批量查询数据库,sthMapper.findByIds(Collection<Long> ids)
对于的guava cache 处理类
// 定义guava缓存
public SthCache() {
sthCache = CacheBuilder.newBuilder()
.maximumSize(SIZE)
.refreshAfterWrite(3, TimeUnit.SECONDS)
.build(new CacheLoader<Long, List<Long>>() {
@Override
public List<Long> load(final Long id) {
return doLoad(Arrays.asList(id)).get(id);
}
@Override
public Map<Long, List<Long>> loadAll(
final Iterable<? extends Long> ids)
throws Exception {
return doLoad(Lists.newArrayList(ids));
}
});
}
// 实际从数据库中加载数据
private Map<Long, List<Long>> doLoad(final List<Long> ids) {
return sthMapper.findByIds(ids);
}
// 批量获取数据
public Map<Long, List<Long>> getSthById(final List<Long> ids) {
return sthCache.getAll(ids);
}
没毛病,getAll(Iterable<? extendsK>)方法用来执行批量查询。默认情况下,对每个不在缓存中的键,getAll方法会单独调用CacheLoader.load来加载缓存项。如果批量的加载比多个单独加载更高效,你可以重载CacheLoader.loadAll来利用这一点。getAll(Iterable)的性能也会相应提升。这边定义了loadAll效率高了。
问题
在debug的时候发现确实走的loadAll,批量查询数据库。但是上线后,线上监控数据却发现这个接口耗时很长,通过分析,发现有很多sthMappper.findByIds()的单个查询。也就是说,并没有调用loadAll,走到批量查询数据库中。
分析解决
- 首先看了下guava的代码实现
ImmutableMap<K, V> getAll(Iterable<? extends K> keys) throws ExecutionException {
int hits = 0;
int misses = 0;
// 省略一大坨
try {
if (!keysToLoad.isEmpty()) {
try {
// 调用loadAll
Map<K, V> newEntries = loadAll(keysToLoad, defaultLoader);
批量查询时,对于没有命中的,确实调用的loadAll来加载数据的。
那问题就不是这边了。在load()方法打了个断点,原因就找到了。

原来是refesh的时候,加载的。refreshAfterWrite 刷新缓存数据时调用的还是load方法。
搜索了下,https://github.com/google/guava/issues/1975 github上这个issue还在。汗!!!
最后我这边解决是用Spring Cache统一了缓存管理。
总结
对于开源库的使用不可只知其然,不知其所以然。
关注公众号【方丈的寺院】,第一时间收到文章的更新,与方丈一起开始技术修行之路

guava缓存批量获取的一个坑的更多相关文章
- Mysql批量更新的一个坑-&allowMultiQueries=true允许批量更新(转)
实际上,我们经常会遇到这样的需求,那就是利用Mybatis批量更新或者批量插入,但是,实际上即使Mybatis完美支持你的sql,你也得看看你说操作的数据库是否支持,而阿福,最近就遇到这样的一个坑. ...
- Mysql批量更新的一个坑-&allowMultiQueries=true允许批量更新
前言 实际上,我们经常会遇到这样的需求,那就是利用Mybatis批量更新或者批量插入,但是,实际上即使Mybatis完美支持你的sql,你也得看看你说操作的数据库是否支持,而阿福,最近就 ...
- Mybatis操作Mysql批量更新的一个坑-&allowMultiQueries=true允许批量更新
前言 利用Mybatis批量更新或者批量插入,实际上即使Mybatis完美支持你的sql,你也得看看你操作的数据库是否完全支持,而同事,最近就遇到这样的一个坑! 问题 先带大家来 ...
- sql 根据指定条件获取一个字段批量获取数据插入另外一张表字段中+MD5加密
/****** Object: StoredProcedure [dbo].[getSplitValue] Script Date: 03/13/2014 13:58:12 ******/ SET A ...
- Guava缓存器源码分析——缓存统计器
Guava缓存器统计器实现: 全局统计器—— 1.CacheBuilder的静态成员变量Supplier<StatsCounter> CACHE_STATS_COUNTER ...
- Google Guava缓存实现接口的限流
一.项目背景 最近项目中需要进行接口保护,防止高并发的情况把系统搞崩,因此需要对一个查询接口进行限流,主要的目的就是限制单位时间内请求此查询的次数,例如1000次,来保护接口. 参考了 开涛的博客聊聊 ...
- springboot集成Guava缓存
很久没有写博客了,这段时间一直忙于看论文,写论文,简直头大,感觉还是做项目比较舒服,呵呵,闲话不多说,今天学习了下Guava缓存,这跟Redis类似的,但是适用的场景不一样,学习下吧.今天我们主要是s ...
- spring中添加google的guava缓存(demo)
1.pom文件中配置 <dependencies> <dependency> <groupId>org.springframework</groupId> ...
- C#程序模拟登录批量获取各种邮件内容信息
一般来说,如果现实中你有这样一种需求“假如你是褥羊毛的羊毛党,你某日发现了一个app有一个活动,通过邮箱注册账号激活可以领5元红包,而恰恰你手上又有一批邮箱可用,那么批量获取邮箱中的激活链接去激活则是 ...
随机推荐
- codeforces 572 C. Lengthening Sticks(数学)
题目链接:http://codeforces.com/contest/572/problem/C 题意:给出a,b,c,l要求a+x,b+y,c+z构成三角形,x+y+z<=l,成立的x,y,z ...
- 深入SpringMVC视图解析器
ViewResolver的主要职责是根据Controller所返回的ModelAndView中的逻辑视图名,为DispatcherServlet返回一个可用的View实例.SpringMVC中用于把V ...
- (转载)非常完善的Log4net配置详细说明
一.前言 在项目中,对项目的日志收集是非常重要的,这里我就说说代码的异常日志收集.收集异常日志,有很多第三方成熟的框架,我这里就介绍一下我常用的Log4net. Log4Net介绍 Log4net 是 ...
- 洛谷 P1525 关押罪犯 NOIp2010提高组 (贪心+并查集)
题目链接:https://www.luogu.org/problemnew/show/P1525 题目分析 通过分析,我们可以知道,这道题的抽象意义就是把一个带边权的无向图,分成两个点集,使得两个集合 ...
- FreeSql (六)批量插入数据
var connstr = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;" + "Initia ...
- AutoCompleteTextView自动完成文本框
AutoCompleteTextView是从EditText派生出来的,比普通编辑框多了一个功能,当用户输入一定字符后,自动完成文本框会显示一个下拉单,供用户选择,当选中一个后,被选中的内容会显示在文 ...
- 记一次Mysql数据库Kill完之后启动不起来的解决方案
在Mysql运行的时候,有时候会stop不了,这时候我们就会想直接把他的进程kill掉. 但是,有时候kill完了之后,在去start它就会直接抛异常了... ERROR! The server qu ...
- 浮动后的 <li> 如何在 <ul> 中居中显示?
百度了许久都没有满意的解决方案,现在终于搞定了. 其实,只要 ul 的父元素 css 样式设了 text-align: center; 然后 ul 设了 display: inline-block; ...
- 各种浏览器UA值
UA User-Agent:用户代理,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本.CPU 类型.浏览器及版本.浏览器引擎.浏览器语言.浏览器插件等. 标准格式为: 浏览器标识 ...
- 01 (OC)* @property 后面可以有哪些修饰符?
一:@property 后面可以有哪些修饰符? 1:线程安全的: atomic,nonatomic 2:访问权限的 readonly,readwrite 3:内存管理(ARC) assign, cop ...