-
2022-04-10 13:16:06
前端缓存主要是分为http缓存和本地缓存
http 缓存
强缓存:Expires(过期时间)/ Cache-Control(no-cache)(优先级高)
协商缓存:Last-Modified/Etag(优先级高)其中 Etag适用于经常改变的小文件 Last-Modified适用于不怎么改变的大文件
强缓存和协商缓存策略:
在缓存命中时都会直接使用本地的缓存副本,区别只在于协商缓存会向服务器发送一次请求,缓存不命中时,都会向服务器发送请求来获取资源。在实际的缓存机制中,强缓存策略和协商缓存策略说一起合作使用的。浏览器首先会根据请求的信息判断,强缓存说否命中,如果命中,则直接使用资源。则直接使用资源。如果不命中则根据头部信息向服务器发起请求,使用协商缓存,如果协商缓存命中,则服务器不放回资源,浏览器直接使用本地资料的副本,如果协商缓存不命中,则浏览器返回最新的资源给浏览器。
本地缓存:
cookie:数据存储不能超过4k,过期时间之前有效,始终在同源的http请求中携带,有path的概念,限制cookie只属于某个路径
webStorage 数据存储可以达到5M,仅在本地保存,不会把数据发送给服务端
localStorage 始终有效,可以用作持久数据
sessionStorage 仅在当前浏览器关闭之前有效
indexDB
以上几种本地缓存的共同点:都是保存在浏览器端,并且是同源的。
更多相关内容 -
Java本地缓存的实现代码
2020-08-30 15:17:28本篇文章主要介绍了Java本地缓存的实现代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 -
Java中LocalCache本地缓存实现代码
2020-08-30 14:27:54本篇文章主要介绍了Java中LocalCache本地缓存实现代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 -
Vue+mui实现图片的本地缓存示例代码
2020-08-27 11:18:29主要介绍了Vue+mui实现图片的本地缓存的实例代码,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下 -
小程序清理本地缓存的方法
2020-10-18 05:17:23主要介绍了小程序清理本地缓存的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 -
微信小程序缓存:本地缓存,同步缓存,异步缓存
2021-03-29 21:47:02关于本地缓存1.wx.setStorage(wx.setStorageSync)、wx.getStorage(wx.getStorageSync)、wx.clearStorage(wx.clearStorageSync)可以对本地缓存进行设置、获取和清理。本地缓存最大为10 ... 关于本地... -
PC用PSV游戏下载工具NPS_Browser+本地缓存文件.zip
2021-01-12 10:52:06②复制:本地缓存文件夹中所有*.tsv文件到NPS_Browser_0.95目录中(任意文件夹亦可,只要你找的到) ③设置:NPS_Browser菜单→文件→设置→游戏列表、DLC、主题这些选项找到对应的*.tsv文件→立即同步缓存 ④下载:... -
Android开发之ImageLoader本地缓存
2020-09-02 22:34:40ImageLoader是一个图片缓存的开源库,提供了强大的图片缓存机制,很多开发者都在使用,今天给大家介绍Android开发之ImageLoader本地缓存。对imageloader本地缓存相关知识感兴趣的朋友一起学习吧 -
PSV工具箱+黑商店+本地缓存文件+config文件+安装图文说明.zip
2021-01-11 15:18:56①安装:PSV工具箱(已安装就...④复制:本地缓存文件 文件里面所有文件,都要复制到PSV根目录下: pkgi 或 pkgj 文件夹中。 ⑤运行:pkgj 刷新! 详细请参考:https://blog.csdn.net/djk8888/article/details/112471090 -
c#K-V本地缓存
2018-11-07 17:16:49c#版本的本地缓存,K-V缓存,实现一般缓存接口。实现FIFO,LRU,LFU策略。通过配置类设置缓存信息,主要设置maxcachesize,cachetime -
本地缓存:为什么要用本地缓存?用它会有什么问题?
2022-04-04 11:13:00随着不断的发展,这一架构也产生了改进,在一些场景下可能单纯使用Redis类的远程缓存已经不够了,还需要进一步配合本地缓存使用,例如Guava cache或Caffeine,从而再次提升程序的响应速度与服务性能。于是,就产生了...背景
在高性能的服务架构设计中,缓存是一个不可或缺的环节。在实际的项目中,我们通常会将一些热点数据存储到Redis或Memcached 这类缓存中间件中,只有当缓存的访问没有命中时再查询数据库。在提升访问速度的同时,也能降低数据库的压力。
随着不断的发展,这一架构也产生了改进,在一些场景下可能单纯使用Redis类的远程缓存已经不够了,还需要进一步配合本地缓存使用,例如Guava cache或Caffeine,从而再次提升程序的响应速度与服务性能。于是,就产生了使用本地缓存作为一级缓存,再加上远程缓存作为二级缓存的两级缓存架构。
在先不考虑并发等复杂问题的情况下,两级缓存的访问流程可以用下面这张图来表示:
为什么要使用本地缓存
- 本地缓存基于本地环境的内存,访问速度非常快,对于一些变更频率低、实时性要求低的数据,可以放在本地缓存中,提升访问速度
- 使用本地缓存能够减少和Redis类的远程缓存间的数据交互,减少网络I/O开销,降低这一过程中在网络通信上的耗时
设计一个本地内存需要有什么功能
- 存储;并可以读、写;
- 原子操作(线程安全),如ConcurrentHashMap
- 可以设置缓存的最大限制;
- 超过最大限制有对应淘汰策略,如LRU、LFU
- 过期时间淘汰,如定时、懒式、定期;
- 持久化
- 统计监控
本地缓存方案选型
1. 使用ConcurrentHashMap实现本地缓存
缓存的本质就是存储在内存中的KV数据结构,对应的就是jdk中线程安全的ConcurrentHashMap,但是要实现缓存,还需要考虑淘汰、最大限制、缓存过期时间淘汰等等功能;
优点是实现简单,不需要引入第三方包,比较适合一些简单的业务场景。缺点是如果需要更多的特性,需要定制化开发,成本会比较高,并且稳定性和可靠性也难以保障。对于比较复杂的场景,建议使用比较稳定的开源工具。
2. 基于Guava Cache实现本地缓存
Guava是Google团队开源的一款 Java 核心增强库,包含集合、并发原语、缓存、IO、反射等工具箱,性能和稳定性上都有保障,应用十分广泛。Guava Cache支持很多特性:
- 支持最大容量限制
- 支持两种过期删除策略(插入时间和访问时间)
- 支持简单的统计功能
- 基于LRU算法实现
使用代码如下:
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>31.1-jre</version> </dependency>
@Slf4j public class GuavaCacheTest { public static void main(String[] args) throws ExecutionException { Cache<String, String> cache = CacheBuilder.newBuilder() .initialCapacity(5) // 初始容量 .maximumSize(10) // 最大缓存数,超出淘汰 .expireAfterWrite(60, TimeUnit.SECONDS) // 过期时间 .build(); String orderId = String.valueOf(123456789); // 获取orderInfo,如果key不存在,callable中调用getInfo方法返回数据 String orderInfo = cache.get(orderId, () -> getInfo(orderId)); log.info("orderInfo = {}", orderInfo); } private static String getInfo(String orderId) { String info = ""; // 先查询redis缓存 log.info("get data from redis"); // 当redis缓存不存在查db log.info("get data from mysql"); info = String.format("{orderId=%s}", orderId); return info; } }
3. Caffeine
Caffeine是基于java8实现的新一代缓存工具,缓存性能接近理论最优。可以看作是Guava Cache的增强版,功能上两者类似,不同的是Caffeine采用了一种结合LRU、LFU优点的算法:W-TinyLFU,在性能上有明显的优越性
使用代码如下:
<dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> <version>2.9.3</version> </dependency>
@Slf4j public class CaffeineTest { public static void main(String[] args) { Cache<String, String> cache = Caffeine.newBuilder() .initialCapacity(5) // 超出时淘汰 .maximumSize(10) //设置写缓存后n秒钟过期 .expireAfterWrite(60, TimeUnit.SECONDS) //设置读写缓存后n秒钟过期,实际很少用到,类似于expireAfterWrite //.expireAfterAccess(17, TimeUnit.SECONDS) .build(); String orderId = String.valueOf(123456789); String orderInfo = cache.get(orderId, key -> getInfo(key)); System.out.println(orderInfo); } private static String getInfo(String orderId) { String info = ""; // 先查询redis缓存 log.info("get data from redis"); // 当redis缓存不存在查db log.info("get data from mysql"); info = String.format("{orderId=%s}", orderId); return info; } }
4. Encache
Encache是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。同Caffeine和Guava Cache相比,Encache的功能更加丰富,扩展性更强:
- 支持多种缓存淘汰算法,包括LRU、LFU和FIFO
- 缓存支持堆内存储、堆外存储、磁盘存储(支持持久化)三种
- 支持多种集群方案,解决数据共享问题
使用代码如下:
<dependency> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> <version>3.9.7</version> </dependency>
@Slf4j public class EhcacheTest { private static final String ORDER_CACHE = "orderCache"; public static void main(String[] args) { CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder() // 创建cache实例 .withCache(ORDER_CACHE, CacheConfigurationBuilder // 声明一个容量为20的堆内缓存 .newCacheConfigurationBuilder(String.class, String.class, ResourcePoolsBuilder.heap(20))) .build(true); // 获取cache实例 Cache<String, String> cache = cacheManager.getCache(ORDER_CACHE, String.class, String.class); String orderId = String.valueOf(123456789); String orderInfo = cache.get(orderId); if (StrUtil.isBlank(orderInfo)) { orderInfo = getInfo(orderId); cache.put(orderId, orderInfo); } log.info("orderInfo = {}", orderInfo); } private static String getInfo(String orderId) { String info = ""; // 先查询redis缓存 log.info("get data from redis"); // 当redis缓存不存在查db log.info("get data from mysql"); info = String.format("{orderId=%s}", orderId); return info; } }
本地缓存问题及解决
1. 缓存一致性
两级缓存与数据库的数据要保持一致,一旦数据发生了修改,在修改数据库的同时,本地缓存、远程缓存应该同步更新。
解决方案1: MQ
一般现在部署都是集群部署,有多个不同节点的本地缓存; 可以使用MQ的广播模式,当数据修改时向MQ发送消息,节点监听并消费消息,删除本地缓存,达到最终一致性;
解决方案2:Canal + MQ
如果你不想在你的业务代码发送MQ消息,还可以适用近几年比较流行的方法:订阅数据库变更日志,再操作缓存。Canal 订阅Mysql的 Binlog日志,当发生变化时向MQ发送消息,进而也实现数据一致性。
2. 本地内存的技术选型问题
- 从易用性角度,Guava Cache、Caffeine和Encache都有十分成熟的接入方案,使用简单。
- 从功能性角度,Guava Cache和Caffeine功能类似,都是只支持堆内缓存,Encache相比功能更为丰富
- 从性能上进行比较,Caffeine最优、GuavaCache次之,Encache最差(下图是三者的性能对比结果)
对于本地缓存的方案中,我比较推荐Caffeine,性能上遥遥领先。虽然Encache功能更为丰富,甚至提供了持久化和集群的功能,但是这些功能完全可以依靠其他方式实现。真实的业务工程中,建议使用Caffeine作为本地缓存,另外使用redis或者memcache作为分布式缓存,构造多级缓存体系,保证性能和可靠性。
-
c# 本地缓存类
2014-04-06 11:00:25WriteCache方法: 用Dictionary, Dictionary, byte[]>替代Cache类 数据库名+表名 为缓存KEY SQL语句为缓存键值的key 查询结果序列化为缓存键值的...序列化后加密保存在本地供调用 ReadCache方法:等分不够了再写。 -
Unity网络正常状态下优先加载网络图片,否则加载本地缓存图片
2018-01-16 16:48:55程序运行后,将获取网络上下载的照片,缓存更新至本地,再次开启无网状态下或网络图片传输异常情况下,程序将读取本地缓存图片。 -
c# 完整本地缓存类
2014-04-06 11:15:08WriteCache方法: 用Dictionary, Dictionary, byte[]>替代Cache类 数据库名+表名 为缓存KEY SQL语句为缓存键值的key 查询结果序列化为缓存键值的Values 序列化后加密保存在本地供调用 ReadCache方法:解密后反序列... -
微信小程序 缓存(本地缓存、异步缓存、同步缓存)详解
2021-01-20 08:25:34关于本地缓存 1.wx.setStorage(wx.setStorageSync)、wx.getStorage(wx.getStorageSync)、wx.clearStorage(wx.clearStorageSync) 可以对本地缓存进行设置、获取和清理。本地缓存最大为10MB 2.localStorage 是... -
Java实现本地缓存
2022-02-15 13:34:59但是对于数据量很小的,访问非常频繁的,我们也可以存在本地缓存中。我将利用concurrentHashMap等集合容器实现一个本地缓存。 1.基于concurrentHashMap的本地缓存。 本地缓存一般使用键值对方式的存储,那么在Java中...对于缓存的作用不言而喻,可以提高查询效率,比去DB查询的速度要快。项目中我们经常会使用Nosql数据库,如Redis等做缓存。但是对于数据量很小的,访问非常频繁的,我们也可以存在本地缓存中。我将利用concurrentHashMap等集合容器实现一个本地缓存。
1.基于concurrentHashMap的本地缓存。
本地缓存一般使用键值对方式的存储,那么在Java中肯定是选用map,由于concurrentHashMap的线程安全性,所以就选择了这个。过期策略采用的定时清除,实现方式可以后台起一个线程去扫,也可以用定时器,本例子使用的是定时器。
/** * 基于concurrentHash的本地缓存工具类 * 缓存删除基于timer定时器 */ public class CacheUtil { //默认大小 private static final int DEFAULT_CAPACITY = 1024; // 最大缓存大小 private static final int MAX_CAPACITY = 10000; //默认缓存过期时间 private static final long DEFAULT_TIMEOUT = 3600; //1000毫秒 private static final long SECOND_TIME = 1000; //存储缓存的Map private static final ConcurrentHashMap<String, Object> map; private static final Timer timer; static { map = new ConcurrentHashMap<>(DEFAULT_CAPACITY); timer = new Timer(); } //私有化构造方法 private CacheUtil() { } /** * 缓存任务清除类 */ static class ClearTask extends TimerTask { private String key; public ClearTask(String key) { this.key = key; } @Override public void run() { CacheUtil.remove(key); } } //==================缓存的增删改查 /** * 添加缓存 */ public static boolean put(String key, Object object) { if (checkCapacity()) { map.put(key, object); //默认缓存时间 timer.schedule(new ClearTask(key), DEFAULT_TIMEOUT); return true; } return false; } /** * 添加缓存 */ public static boolean put(String key, Object object, int time_out) { if (checkCapacity()) { map.put(key, object); //默认缓存时间 timer.schedule(new ClearTask(key), time_out * SECOND_TIME); } return false; } /** * 判断容量大小 */ public static boolean checkCapacity() { return map.size() < MAX_CAPACITY; } /** * 批量增加缓存 */ public static boolean put(Map<String, Object> m, int time_out) { if (map.size() + m.size() <= MAX_CAPACITY) { map.putAll(map); for (String key : m.keySet()) { timer.schedule(new ClearTask(key), time_out * SECOND_TIME); } return true; } return false; } /** * 删除缓存 */ public static void remove(String key) { map.remove(key); } /** * 清除所有缓存 */ public void clearAll() { if (map.size() > 0) { map.clear(); } timer.cancel(); } /** * 获取缓存 */ public static Object get(String key) { return map.get(key); } /** * 是否包含某个缓存 */ public static boolean isContain(String key) { return map.contains(key); } }
每日一道Java面试题
点击关注支持一下:Java有话说
-
ReactNative网路及本地缓存
2019-03-15 16:14:28ReactNative网路及本地缓存 Fetch之get请求数据, Fetch之Post请求数据, AsyncStorageDemo本地缓存数据 -
分布式缓存和本地缓存的区别
2022-03-18 11:00:45分布式缓存和本地缓存的区别redis/memcached**分布式缓存**和map/guava**本地缓存**的区别什么是缓存一致性? redis/memcached分布式缓存和map/guava本地缓存的区别 缓存分为本地缓存和分布式缓存,使用map或guava...分布式缓存和本地缓存的区别
redis/memcached分布式缓存和map/guava本地缓存的区别
- 缓存分为本地缓存和分布式缓存,使用map或guava的是本地缓存,轻量而快速,随着jvm的销毁而结束,多实例情况下,每个实例都保存一份缓存,缓存不具有一致性。
- 分布式缓存,多实例情况下,各实例共用一份缓存数据,缓存具有一致性。缺点,架构复杂,要保证服务的高可用。
什么是缓存一致性?
用户在成都新增了数据,同时修改一条数据,上海删除了数据,这时成都告诉另外两个缓存服务新增和删除,上海告诉另外两个缓存服务删除,如果新增冲突了,网络延时了,消息到达顺序与发送的顺序不一致了,网络不通了等等,怎么办,怎么办,乱了,全乱了。。。数据的一致性是非常难解决的。这就是所说的缓存不一致情况! -
vue的本地缓存
2022-01-14 11:35:59实现效果:将表格内容没保存用缓存存储,点击保存后存储到api。 1.给输入框添加一个按键松开事件,@keyup 注意:在element-ui组件@keyup不起作用。这是因为element-ui组件在原生组件的基础上进行了封装。... -
redis本地缓存与redis缓存
2022-02-14 15:53:40redis本地缓存与redis缓存 -
SpringBoot + Caffeine本地缓存
2021-06-21 09:50:12缓存常量CacheConstants2.缓存枚举类CacheEnum3.缓存配置类CacheConfig4.项目中使用 SpringBoot + Caffeine配置 Caffeine 是基于 JAVA 8 的高性能缓存库。并且在 spring5 (springboot 2.x) 后spring 官方放弃了 ... -
SpringBoot Cache 配置本地缓存
2022-04-29 16:23:57--spring-缓存依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> 2.配置Cache @... -
Springboot本地缓存和redis缓存
2020-08-30 19:57:14建表)降低了复杂度,但数据库在数据量过大、高并发等场景出现时也会出现瓶颈,这时有两种解决方案,一是换高并发处理、负载均衡和分布式数据库(如:HANA-成本高),二是放缓存(纳秒)里,还有一种折中的方法就是... -
Java本地缓存工具,LoadingCache的使用(附代码) | Java工具类
2021-12-31 15:05:30在工作总常常需要用到缓存,而redis往往是首选,但是短期的数据缓存一般我们还是会用到本地缓存。本文提供一个我在工作中用到的缓存工具,该工具代码为了演示做了一些调整。如果拿去使用的话,可以考虑做成注入Bean... -
本地缓存
2018-07-07 21:32:21首先来简单了解缓存系统的分类,缓存系统按照缓存数据的存储方式可以分为本地缓存和集中式缓存两种。 本地缓存:缓存数据保存在单个应用服务器中,各个应用服务器之间的缓存数据是独立的。 集中式缓存:缓存... -
Caffeine本地缓存详解(一篇就明白)
2021-07-19 21:51:37结论:Caffeine 是目前性能最好的本地缓存,因此,在考虑使用本地缓存时,直接选择 Caffeine 即可。 先看一个小例子,明白如何创建一个 Caffeine 缓存实例。 Caffeine caffeine = Caffeine.newBuilder() .... -
分布式缓存redis+本地缓存Caffeine:多级缓存架构在行情系统中的应用
2020-01-08 19:38:08多级缓存架构在行情系统中的应用