查看小程序缓存数据的网站-《每日分享》性能优化本地缓存神器-guavacache

点击上方“java全栈技术”关注,每天晚上学习一个java知识点

系统中,本地缓存适用于一些访问量较大、数据量较小、与业务无关的缓存。 为什么不使用分布式缓存呢? 分布式集群缓存的建立和维护成本较高,不适合紧急项目。 本地缓存访问速度快,使用方便,但缺点是无法保证数据更新的一致性,使用范围有限。 GuavaCache 是本地缓存的最佳选择,我们明天就会知道。 以下是本文的内容提纲:

通过guavacache的优势和使用场景来判断业务中是否适合使用这款缓存。 介绍常用技术,并给出示例,作为深入分析源码的参考。

番石榴简介

Guacache 是一个本地缓存。 具有以下优点:

常用技能

批量操作就是循环调用对应的方法,如:

GuavaCache中缓存的容器被定义为socket Cache的实现类。 该实现类是线程安全的,因此一般定义为单例。 以下是官方demo:

回收政策

常用的定时恢复,以下是三种基于时间的方法来清除或刷新缓存数据:

expireAfterAccess:当缓存项在指定时间段内没有被读写时,就会被回收。

expireAfterWrite:当缓存项在指定的时间内没有更新时,就会被回收。

freshAfterWrite:缓存项上次更新操作后多久刷新

考虑到时效性,我们可以使用expireAfterWrite在每次更新后的指定时间使缓存失效,然后重新加载缓存。 Guacache会严格限制只有一次加载操作,这样会防止大量缓存失效请求渗透到前端,造成雪崩效应。

但通过分析源码,guavacache只锁定了一个加载操作,其他请求必须阻塞等待加载操作完成; 加载完成后,其他请求线程会一一获取锁,判断自己是否已被锁定。 加载完成后查看小程序缓存数据的网站,每个线程都要轮流经历“获取锁、获取值、释放锁”的过程,这会造成一定的性能损失。 这里,因为我们计划在本地缓存一秒,所以频繁的过期加载、锁等待等过程会造成性能上的较大损失。

为此,我们考虑使用refreshAfterWrite。 freshAfterWrite的特点是在刷新过程中,严格限制只有一次重载操作,而其他查询则先返回旧值,这样可以有效减少等待和锁争用,所以refreshAfterWrite会比expireAfterWrite表现更好。 而且它也有一个缺点,因为达到指定时间后,它不能严格保证所有查询都会得到新值。 了解过Guacache定时失效(或者说刷新)的朋友都知道,Guacache并没有使用额外的线程来执行定时的清除和加载功能,而是依赖于查询请求。 查询时,比较之前的更新时间,如果超过指定时间,则加载或刷新。 因此查看小程序缓存数据的网站,如果使用refreshAfterWrite,在吞吐量较低的情况下,如果长时间没有查询,发生的查询可能会得到一个盲值(这个盲值可能来自很久以前),这会导致问题。

可见refreshAfterWrite和expireAfterWrite这两种形式既有异同。

Guacache源码分析

示例代码:

首先了解一些主要的类和socket:

综上所述,guavacache的核心操作都是在LocalCache中实现的。

其他:

查看小程序缓存数据的网站-《每日分享》性能优化本地缓存神器-guavacache

在看具体代码之前,我们先简单了解一下LocalCache的数据结构。

LocalCache的数据结构如下:

LocalCache的数据结构与ConcurrentHashMap非常相似。 两者都是由多个Segment组成,每个Segment相对独立,互不影响,因此可以支持并行操作。 每个段由一个表和多个队列组成。 缓存的数据存储在表中,表的类型为AtomicReferenceArray>,即链表,链表中的每个元素都是一个数组。 这两个队列分别是writeQueue和accessQueue,分别用于存储写入的数据和最近访问的数据。 当数据过期,需要刷新整体缓存时(见上例中最后一个cache.getIfPresent("key5")),就会遍历队列。 如果数据过期,则会从表中删除。 段中根据参考场景还有其他队列,这里不再讨论。

缓存生成器

CacheBuilder是一个缓存配置和建立入口,我们先看一些属性。 CacheBuilder的设置操作就是针对那些属性参数的。

CacheBuilder构建缓存有两种方式:

查看小程序缓存数据的网站-《每日分享》性能优化本地缓存神器-guavacache

本地缓存

LocalCache是​​guavacache的核心类。 LocalCache的构造函数在里面已经分析过了,接下来看核心技巧。

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

getAll(keys) 方法:

查看小程序缓存数据的网站-《每日分享》性能优化本地缓存神器-guavacache

put(键,值)方法:

putAll(map) 在循环中调用 put 技巧。

在 putIfAbsent(key,value) 缓存中,只有当通配符对不存在时才会插入。

实践

Guavacache将数据源中的数据缓存在本地,那么如果我们想将远程数据源中的数据缓存在远程分布式缓存(如redis)中,我们该如何使用guavacache方法来封装呢?

可以模仿guava写一个简单的缓存,定义如下:

CacheBuilder类:配置缓存参数并构建缓存。 与前面提到的相同。

缓存socket:定义增、删、查的socket。

MyCache类:实现Cache套接字,put->store到DB,更新缓存; get->查询缓存,如果存在则返回; 如果没有,则查询DB,更新缓存,返回。

CacheLoader类:被MyCache调用,在get、getAll时提供单查询DB和批量查询DB。

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 网站程序 查看小程序缓存数据的网站-《每日分享》性能优化本地缓存神器-guavacache https://www.wkzy.net/game/158751.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务