Guava Cache小记

review代码时看到的问题,小记一下。
 

1. 使用Guava Cache的四个理由

 

1.1 entry不存在或失效时,保证单线程回源

避免了所有读不到该entry的线程一起去后面的数据库或Redis访问,压力暴炸。虽然自己做也行,但不就怕普通程序员一不小心没写好么。

 

1.2 后台定时刷新数据

数据放入缓存后,定时刷新,而且在正确配置后(后详),在刷新的过程中,依然使用旧数据响应请求,不会造成卡顿,非常美好。

 

1.3 WeakHashMap的并发安全版

Map里的Key或Value是 WeakReference的好处,就是对象本身失效后被GC掉,而不会因为对象依然在Map里保存而GC不掉。

可惜JDK自身提供的WeakHashMap,并没有Concurrent的版本,此时就可以考虑GuavaCache了。

我就是不用Guva Cache呢,那就用一个有expireTime的本地缓存,让它在失效后再被GC掉吧。

 

1.4 本地缓存中传统的expiretime,maxSize限制

略。

 

2. 使用Guava Cache的正确使用

 

2.1 设置并发级别

Guava Cache 是JDK7 ConcurrentHashMap的思路,先分N个Segment加锁,Segment下面才是HashMap。这样就把原本一个锁,打散成N个锁。
但和ConcurrentHashMap默认16个锁不一样,GuavaCache默认是4个锁,自己看着设置。

 

2.2 设置后台刷新

如果你什么都不做,只是设置 CacheBuilder.newBuilder().refreshAfterWrite(30, TimeUnit.SECONDS),那CacheLoader巧妇难为无米之炊之炊,还是要在当前线程里执行加载,还是会造成卡顿的。君不见CacheLoader中reload()的实现:

return Futures.immediateFuture(load(key));

所以,要后台刷新,一定要重载reload函数,给它一条执行的线程。

CacheLoader里本身有一个静态函数,只要传给它原来的CacheLoader 和 一个executor,它会返回一个修饰器模式的包装类,重新实现reload()函数,以callable在executor里执行load()函数。

public static CacheLoader asyncReloading(final CacheLoader loader, final Executor executor)

但这也怕这包装类万一没被内联,白白多了层调用啊,所以还是不要这么懒,自己把它的reload()方法抄出来,抄到自己的CacheLoader 或者一个公用的CacheLoader父类里了。

另外,如果executor給多个CacheLoader共用,最好用一个core pool size为1的,CachedPool风格的池。

 

2.3 get()与uncheckGet()

get()抛的是 Checked的 ExecutionException,另外还要做一次getCause()才能获得真正的异常,主要是load()里发生的Checked异常。

getUnchecked()则抛的是UncheckedExecutionException,还是要做getCause()哈。当然如果严重错误Error,还是会抛ExecutionError的,但这不用在接口里声明。

This entry was posted in 技术. Bookmark the permalink.

5 Responses to Guava Cache小记

  1. realsky says:

    老板,美女图呢?

  2. 言不由中 says:

    请教大神:
    "另外,如果executor給多个CacheLoader共用,最好用一个core pool size为1的,CachedPool风格的池。"

    具体指的是什么?有什么参考资料吗?我搜索了,没搜到合适的。

    是说maximumPoolSize 设置成Integer.MAX_VALUE还是也设置成1?

    目的和效果是什么,谢谢指点。

  3. 匿名 says:

    Guava Cache 早期版本也会存在并发问题

发表评论

您的电子邮箱不会被公开。

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>