前端缓存&本地缓存&分布式缓存

本文详细介绍了Mysql的一级缓存、二级缓存、SpringBoot内置缓存以及Redis缓存配置,还探讨了事务对一级缓存的影响,前端H5的sessionStorage和localStorage在缓存中的应用,以及在高并发场景下的缓存生产和前端缓存策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

常见的缓存有哪些?

  1. Mysql一级缓存
  2. Mysql二级缓存
  3. 本地缓存
  4. 分布式缓存
  5. 前端h5的sessionStorage
  6. 前端h5的localStorage

1. mybatis一级缓存


![[Pasted image 20240306094236.png]]

public List<TrainQueryResp> queryAll(){  
    List<Train> trainList=selectAll();  
    LOG.info("再查一次");  
    trainList=selectAll();  
    return BeanUtil.copyToList(trainList,TrainQueryResp.class);  
}

这段代码在查询火车的车次时会查询两次!但是当为该方法加入注解@Transactional,使该方法变为一个事务时,便只会查询一次(这就是事务的一级缓存,只要事务一旦结束,缓存就会消失)

public List<Train> selectAll(){  
    //按code升序排序,TrainExample是用来封装查询条件的  
    TrainExample trainExample=new TrainExample();  
    //orderByClause是用来指定排序的  
    trainExample.setOrderByClause("code asc");  
    return trainMapper.selectByExample(trainExample);  
}

这是因为在第一个查询时,trainMapper.selectByExample(trainExample)会执行,然后将结果缓存,第二次查询时直接拿到结果
这样可以减少查询次数


一级缓存如何关闭呢?
在配置文件中加入

mybatis-configuration.local-cache-scope=session/statement

默认是session(会话)级别的,在一次会话中进行缓存
选用statement,每执行一次SQL,就会清空缓存

2. mybatis的二级缓存


二级缓存默认是关闭的,需要手动开启;
在需要使用二级缓存的Mapper文件中加入

<cache> </cache>

![[Pasted image 20240306101418.png]]

同时需要将实体类序列化,为该实体类implements Serializable即可
![[Pasted image 20240306101432.png]]

此后在第二次执行同一SQL语句时便不会再去查询数据库,而是直接使用缓存中的数据


那么二级缓存如何使之失效呢?

使用增删改SQL语句,即使没有改变数据,Mybatis都会将同个命名空间下的二级缓存清空

一级缓存的作用域是一次会话,二级缓存的作用域是同一命名空间

3. SpringBoot内置缓存


在pom文件中加入依赖(版本与springboot版本一致),同时在启动类中加入注解@EnableCaching

<!--spring内置缓存-->  
<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-cache</artifactId>  
</dependency>

目前做到这些可以说是支持缓存!
每个Service需要单独配置,才能自己开启;其中value值自定义
在这里插入图片描述

![[Pasted image 20240306103607.png]]

所以需要重写equals方法和hashCode方法使得对于我们要求的参数相同即可判断是相同的执行过程
![[Pasted image 20240306103941.png]]

4. redis缓存配置


//设置缓存类型为redis
spring.cache.type=redis  
//使用缓存key的前缀
spring.cache.redis.use-key-prefix=true  
spring.cache.redis.key-prefix=train_cache_  
spring.cache.redis.cache-null-values=true  
spring.cache.redis.time-to-live=60s

5. 缓存在高并发场景下的生产问题


![[Pasted image 20240306112132.png]]

6. 前端缓存


在很多个页面都会去获取火车车次数据,其实这个请求可以只请求一次,后面使用缓存即可(因为车站数据基本不会变化)

使用SeeionStorage,在一个js文件下定义

SESSION_ALL_TRAIN = "SESSION_ALL_TRAIN";  
  
SessionStorage = {  
    get: function (key) {  
        var v = sessionStorage.getItem(key);  
        if (v && typeof(v) !== "undefined" && v !== "undefined") {  
            return JSON.parse(v);  
        }  
    },  
    set: function (key, data) {  
        sessionStorage.setItem(key, JSON.stringify(data));  
    },  
    remove: function (key) {  
        sessionStorage.removeItem(key);  
    },  
    clearAll: function () {  
        sessionStorage.clear();  
    }  
};

使用:

/**  
 * 查询所有的车次,用于车次下拉框  
 */  
const queryAllTrain = () => {  
  let list = SessionStorage.get(SESSION_ALL_TRAIN);  
  if (Tool.isNotEmpty(list)) {  
    console.log("queryAllTrain 读取缓存");  
    trains.value = list;  
  } else {  
    axios.get("/business/admin/train/query-all").then((response) => {  
      let data = response.data;  
      if (data.success) {  
        trains.value = data.content;  
        console.log("queryAllTrain 保存缓存");  
        SessionStorage.set(SESSION_ALL_TRAIN, trains.value);  
      } else {  
        notification.error({description: data.message});  
      }  
    });  
  }  
};
### 本地缓存的实现方式 本地缓存通常是指将数据存储在应用程序所在的同一台机器上,通常是内存中的某种形式。这种方式能够提供极低延迟的数据访问能力,因为它不需要网络通信开销。常见的实现方式包括但不限于 `HashMap`、`ConcurrentHashMap` 和开源框架如 Guava Cache、Caffeine 等[^3]。 #### 使用 `ConcurrentHashMap` 实现本地缓存 `ConcurrentHashMap` 是 JDK 提供的一个线程安全的哈希表实现,在多线程环境下具有较高的性能表现。它允许完全并发读取操作,并支持高效的写入锁分段机制。以下是基于 `ConcurrentHashMap` 的简单本地缓存实现: ```java import java.util.concurrent.ConcurrentHashMap; public class LocalCache&lt;K, V&gt; { private final ConcurrentHashMap&lt;K, V&gt; cacheMap = new ConcurrentHashMap&lt;&gt;(); public void put(K key, V value) { cacheMap.put(key, value); } public V get(K key) { return cacheMap.get(key); } public void remove(K key) { cacheMap.remove(key); } public void clear() { cacheMap.clear(); } } ``` 上述代码展示了如何利用 `ConcurrentHashMap` 构建一个简单的本地缓存类[^5]。 --- ### 缓存机制 缓存机制主要涉及以下几个方面: 1. **加载策略**:当请求某个键对应的值时,如果该值不存在于缓存中,则需要从底层数据源(如数据库)获取并填充到缓存中。 2. **淘汰策略**:由于内存资源有限,缓存无法无限增长,因此需要定义合理的淘汰规则来移除不再使用的条目。 3. **失效控制**:为了防止缓存中的数据长期未更新而变得陈旧,可以设定每项数据的有效期限。 例如,Guava Cache 支持通过配置指定最大容量以及超时时间 (TTL),从而自动化管理这些过程。 --- ### 常见的缓存策略 不同的业务场景可能适合不同类型的缓存策略,下面列举几种典型的算法及其适用范围: - **LRU (Least Recently Used)** LRU 表示最近最少使用原则,即优先保留那些被频繁访问过的对象,而对于长时间未曾触及的内容则予以清除。这种方案适用于大多数通用情况下的内存优化需求。 - **LFU (Least Frequently Used)** LFU 则关注的是频率维度上的差异性处理&mdash;&mdash;越是经常发生的查询越应该驻留在高速缓冲区里头;反之亦然。 - **FIFO (First In First Out)** FIFO 方法按照先进先出的原则决定哪些记录应当被淘汰出局。尽管其实现起来比较简单明了,但在某些特定条件下可能会导致较差的效果。 对于更复杂的场景,还可以考虑混合型或多层架构的设计思路,比如 Redis 客户端缓存结合本地嵌套式布局等方式共同发挥作用[^1]。 --- ### 结合 MyBatis 的本地缓存功能 MyBatis 自带了一种称为&ldquo;一级缓存&rdquo;的特性,默认情况下会自动开启用于减少重复 SQL 执行次数所带来的额外负担。除此之外还存在另外两种扩展选项:&ldquo;二级缓存&rdquo;与&ldquo;集群缓存&rdquo;,它们分别作用于跨多个 Mapper 文件共享全局状态层面之上以及分布式的环境中保持同步一致性的目标达成之中[^2]。 启用或禁用此类行为可通过 XML 映射文档内的属性声明完成调整工作,如下所示: ```xml &lt;select id=&quot;selectUserById&quot; resultType=&quot;User&quot; flushCache=&quot;false&quot;&gt; SELECT * FROM users WHERE id=#{id}; &lt;/select&gt; ``` 这里设置了参数 `flushCache=&quot;false&quot;` 意味着不会每次调用都强制刷新掉现有的临时保存区域内容。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值