摘要

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,走到批量查询数据库中。

分析解决

  1. 首先看了下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缓存批量获取的一个坑的更多相关文章

  1. Mysql批量更新的一个坑-&allowMultiQueries=true允许批量更新(转)

    实际上,我们经常会遇到这样的需求,那就是利用Mybatis批量更新或者批量插入,但是,实际上即使Mybatis完美支持你的sql,你也得看看你说操作的数据库是否支持,而阿福,最近就遇到这样的一个坑. ...

  2. Mysql批量更新的一个坑-&allowMultiQueries=true允许批量更新

    前言        实际上,我们经常会遇到这样的需求,那就是利用Mybatis批量更新或者批量插入,但是,实际上即使Mybatis完美支持你的sql,你也得看看你说操作的数据库是否支持,而阿福,最近就 ...

  3. Mybatis操作Mysql批量更新的一个坑-&allowMultiQueries=true允许批量更新

    前言            利用Mybatis批量更新或者批量插入,实际上即使Mybatis完美支持你的sql,你也得看看你操作的数据库是否完全支持,而同事,最近就遇到这样的一个坑! 问题 先带大家来 ...

  4. sql 根据指定条件获取一个字段批量获取数据插入另外一张表字段中+MD5加密

    /****** Object: StoredProcedure [dbo].[getSplitValue] Script Date: 03/13/2014 13:58:12 ******/ SET A ...

  5. Guava缓存器源码分析——缓存统计器

    Guava缓存器统计器实现: 全局统计器——         1.CacheBuilder的静态成员变量Supplier<StatsCounter> CACHE_STATS_COUNTER ...

  6. Google Guava缓存实现接口的限流

    一.项目背景 最近项目中需要进行接口保护,防止高并发的情况把系统搞崩,因此需要对一个查询接口进行限流,主要的目的就是限制单位时间内请求此查询的次数,例如1000次,来保护接口. 参考了 开涛的博客聊聊 ...

  7. springboot集成Guava缓存

    很久没有写博客了,这段时间一直忙于看论文,写论文,简直头大,感觉还是做项目比较舒服,呵呵,闲话不多说,今天学习了下Guava缓存,这跟Redis类似的,但是适用的场景不一样,学习下吧.今天我们主要是s ...

  8. spring中添加google的guava缓存(demo)

    1.pom文件中配置 <dependencies> <dependency> <groupId>org.springframework</groupId> ...

  9. C#程序模拟登录批量获取各种邮件内容信息

    一般来说,如果现实中你有这样一种需求“假如你是褥羊毛的羊毛党,你某日发现了一个app有一个活动,通过邮箱注册账号激活可以领5元红包,而恰恰你手上又有一批邮箱可用,那么批量获取邮箱中的激活链接去激活则是 ...

随机推荐

  1. java基础面试(二)

    最近有搜了几个面试题,大家一起来探讨一下. 1.Oracle 的分页 --分页查询一 select * from (select a1.*,rownum rn from (select * from ...

  2. 【Offer】[43] 【1~n整数中1出现的次数】

    题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 输入一个整数n,求1~n这n个整数的十进制表示中1出现的次数.例如,输入12, 1~12这些整数中包含1的数字有1.10.11和12,1 ...

  3. 详解JAVA字符串类型switch的底层原理

    基础 我们现在使用的Java的版本,基本上是都支持String类型的.当然除了String类型,还有int.char.byte.short.enum等等也都是支持的.然而在其底部实现中,还是基于 整型 ...

  4. Maven工程读取properties文件过程

    1.创建需要读取的properties文件 2.在xml文件中加载配置文件 <!-- 加载配置文件 --> <context:property-placeholder locatio ...

  5. 更换SVN项目资源库目录出现的问题

    今天在做SVN资源库管理时出现了如下问题: 因为当时把资源库地址写错了,所以想换个资源库,所以先断开资源库 然后我重新导入新的资源库位置: 于是就出现了这种问题: 其实这个问题困扰我好久了之前一直放过 ...

  6. 洛谷 P1091合唱队列

    吾王剑之所指,吾等心之所向                           ——<Fate/stay night> 题目:https://www.luogu.org/problem/P ...

  7. CentOS7 常用命令

    常用命令 1.文件与目录操作 命令 解析 cd /home 进入 ‘/home’ 目录 cd .. 返回上一级目录 cd ../.. 返回上两级目录 cd - 返回上次所在目录 cp file1 fi ...

  8. Linux 笔记 - 第二十章 配置 Nginx 反向代理和负载均衡

    一.简介 由于 Nginx 的反向代理和负载均衡功能经常被提及,所以将这两个功能单独提出来进行讲解. Nginx 其实仅仅是作为 Nginx Proxy 反向代理使用的,因为这个反向代理功能表现的效果 ...

  9. linux 操作系统级别监控 vmstat/dstat 命令

    vmstat命令综合了CPU.进程.内存.磁盘IO等信息 命令:vmstat 1       表示vmstat每2秒采集数据,一直采集,直到我结束程序 vmstat 2 1    表示每个两秒采集一次 ...

  10. django配置静态文件的两种方法

    方法一:按照django配置静态文件的方法,可以在APP应用目录下创建一个static的文件夹,然后在static文件夹下创建一个和APP同名的文件夹,如我有一个blog的django项目,在下面有一 ...