Guava cache 学习01 简介 && 使用_加载数据

在官方的文档说明中,Guava Cache实现了三种加载缓存的方式:

LoadingCache在构建缓存的时候,使用build方法内部调用CacheLoader方法加载数据

在使用get方法的时候,如果缓存不存在该key或者key过期等,则调用get(K, Callable)方式加载数据;

直接调用put方法来放置缓存

Guava cache 学习01 简介 && 使用_加载_02

Guava cache 学习01 简介 && 使用_加载_03

自然先看下核心实现localCache


在实现上,LocalCache的并发策略和ConcurrentHashMap的并发策略一致,也是进行了分段,支持不同段的并发写入。


https://www.cnblogs.com/shoren/p/guava_cache.html


guava cache是一个本地缓存。有以下优点:


很好的封装了get、put操作,能够集成数据源。

一般我们在业务中操作缓存,都会操作缓存和数据源两部分。如:put数据时,先插入DB,再删除原来的缓存;ge数据时,先查缓存,命中则返回,没有命中时,需要查询DB,再把查询结果放入缓存中。 guava cache封装了这么多步骤,只需要调用一次get/put方法即可。

线程安全的缓存,与ConcurrentMap相似,但前者增加了更多的元素失效策略,后者只能显示的移除元素。

Guava Cache提供了三种基本的缓存回收方式:基于容量回收、定时回收和基于引用回收。定时回收有两种:按照写入时间,最早写入的最先回收;按照访问时间,最早访问的最早回收。

监控缓存加载/命中情况。

对于get(key, loader)方法流程:


对key做hash,找到存储的segment及数组table上的位置;

链表上查找entry,如果entry不为空,且value没有过期,则返回value,并刷新entry。

若链表上找不到entry,或者value已经过期,则调用lockedGetOrLoad。

锁住整个segment,遍历entry可能在的链表,查看数据是否存在是否过期,若存在则返回。若过期则删除(table,各种queue)。若不存在,则新建一个entry插入table。放开整个segment的锁。

锁住entry,调用loader的reload方法,从数据源加载数据,然后调用storeLoadedValue更新缓存。

storeLoadedValue时,锁住整个segment,将value设置到entry中,并设置相关数据(入写入/访问队列,加载/命中数据等)。

getAll(keys)方法:


循环调用get方法,从缓存中获取key对应的value。没有命中的记录下来。

如果有没有命中的key,调用loadAll(keys,loader)方法加载数据。

将加载的数据依次缓存,调用segment的put(K key, int hash, V value, boolean onlyIfAbsent)方法。

put时,锁住整个segment,将数据插入链表,更新统计数据。

put(key,value)方法:


对key做hash,找到segment的位置和table上的位置;

锁住整个segment,将数据插入链表,更新统计数据。

putAll(map) 循环调用put方法。


putIfAbsent(key, value) 缓存中,键值对不存在的时候才插入。