Caffeine本地缓存技术

说明:Caffeine是本地缓存方案,在所有本地缓存中命中率最佳,参考下图(引自http://t.csdn.cn/oiQlH),本文介绍Caffeine在SpringBoot项目中的应用。

在这里插入图片描述

使用

例如现在有两个接口,一个查询所有用户,一个根据ID查询用户,数据访问层使用的是Mybatis-plus;

controller层代码如下:

import com.hzy.pojo.User;
import com.hzy.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("list")
    public List<User> getUsers() {
        return userService.list();
    }

    @GetMapping("{id}")
    public User getUserById(@PathVariable Long id) {
        return userService.getById(id);
    }
}

第一步:引入依赖

使用Caffeine前先引入相关依赖:

	<dependency>
	    <groupId>com.github.ben-manes.caffeine</groupId>
	    <artifactId>caffeine</artifactId>
	</dependency>

第二步:创建Bean对象

针对需要用本地缓存的接口,创建对应的缓存对象,注意导包是"com.github……"里面的

(创建一个配置类)

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.hzy.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CaffeineConfig {

    /**
     * 创建User相关接口的Cache对象,缓存数量上限为100,初始容量为10
     * @return
     */
    @Bean
    public Cache<Long, User> userCache(){
        return Caffeine.newBuilder()
                .initialCapacity(10)
                .maximumSize(100)
                .build();

    }
}

顺便一提,Caffeine提供了三种缓存驱逐策略,分别如下:

  • 基于容量,设置缓存数量的上限;
Cache<String, String> cache = Caffeine.newBuilder()
    .maximumSize(100)	// 设置缓存数量上限
    .build();
  • 基于时间,设置缓存的有效时间;
Cache<String, String> cache = Caffeine.newBuilder()
    .expireAfterWrite(Duration.ofSeconds(10)) 	  // 设置缓存有效期为最后一次写入后的10秒
    .build();
  • 基于引用,设置缓存为软件引用或者弱引用,利用JVM虚拟机的GC来回收缓存,性能差,不推荐;

第三步:修改代码

可以针对这两个接口,在Service层输入信息,来判断缓存是否生效,有没有每次都访问数据库;

(controller层,方法改为访问Service的方法,查询所有的接口不使用缓存)

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private Cache<Long, User> userCache;

    /**
     * 不使用缓存
     * @return
     */
    @GetMapping("list")
    public List<User> getUsers() {
        return userService.list();
    }

    /**
     * 使用缓存
     * @param id
     * @return
     */
    @GetMapping("{id}")
    public User getUserById(@PathVariable Long id) {
        return userCache.get(id, new Function<Long, User>() {
            @Override
            public User apply(Long key) {
                return userService.getUserById(key);
            }
        });
    }
}

(Service层代码,每次访问数据库前打印信息)

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Override
    public User getUserById(Long id) {

        System.out.println("根据ID查询用户接口====访问了数据库");

        return getById(id);
    }
}

第四步:测试使用

启动项目,使用Postman访问根据ID查询用户的接口,查看控制台结果;

(首次访问,控制台打印信息,请求访问了数据库)

在这里插入图片描述

在这里插入图片描述

清空控制台,二次访问,未打印信息,说明这次没有访问数据库,缓存生效了。此时即使停用数据库,这条请求依旧可以访问到结果

在这里插入图片描述

在这里插入图片描述

注意事项

使用Caffeine可以减轻数据库压力,但是需要注意,因为Caffeine是本地缓存,重启项目后发送请求还是直接访问数据库的。

另外,Caffeine好像不能使用Mybatis-Plus提供的,list()、selectList()这种全查的API,就是说只能在单条记录的查询下使用Caffeine,比较受限。

即便可以对list()、selectList()查询结果缓存,那Caffeine有没有对缓存进行管理呢?比如全查了所有用户信息,保留了缓存。此时首次查询一条用户信息,Caffeine有没有相关判断,直接从缓存中获取此次查询结果,而不访问数据库呢?值得思考。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/50760.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

分析npm run serve之后发生了什么?

首先需要明白的是&#xff0c;当你在终端去运行 npm run ****&#xff0c;会是什么过程。 根据上图的一个流程&#xff0c;就可以衍生出很多问题。 1&#xff0c;为什么不直接运行vue-cli-service serve? 因为直接运行 vue-cli-service serve&#xff0c;会报错&#xff0c…

数字光源控制器报警说明

Revision Sheet: Rev Data Author Description 1.0 20230729 Shuangyi 数字光源控制器报警说明 V1.0 一.报警说明 当我们所连接的光源负载超出光源控制器本身驱动能力的时候&#xff0c;我们会对控制器进行保护&#xff0c;从以下方式可知道过流的情况&#xff0c;如…

【信号去噪】基于马氏距离和EDF统计(IEE-TSP)的基于小波的多元信号去噪方法研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

数据可视化(2)

1.柱状图 #柱状图 #bar(x,height,width,*,aligncenter,**kwargs) #height柱子的高度&#xff0c;即y轴上的数据 #width数组的宽度&#xff0c;默认值0.8 #*表示后面的参数为匿名关键字&#xff0c;必须传入参数 #kwargs关键字参数x[1,2,3,4,5] height[random.randint(10,100)f…

【学习笔记】视频检测方法调研

目录 1 引言2 方法2.1 视频目标跟踪2.1.1 生成式模型方法2.1.2 判别式模型方法2.1.2.1 基于相关滤波跟踪2.1.2.2 基于深度学习跟踪 2.2 视频异常检测2.2.1 基于重构方法2.2.2 基于预测方法2.2.3 基于分类方法2.2.4 基于回归方法 2.3 深度伪造人脸视频检测2.3.1 基于RNN时空融合…

WIZnet W6100-EVB-Pico DHCP 配置教程(三)

前言 在上一章节中我们讲了网络信息配置&#xff0c;那些网络信息的配置都是用户手动的去配置的&#xff0c;为了能跟电脑处于同一网段&#xff0c;且电脑能成功ping通板子&#xff0c;我们不仅要注意子网掩码&#xff0c;对于IP地址主机位和网络位的划分&#xff0c;而且还要注…

【LeetCode】二叉树的前序,中序,后序遍历

此题用递归做比较容易&#xff0c;然后根据前中后的遍历特点&#xff1a; 前序是根左右&#xff0c; 中序是左根右&#xff0c; 后序是左右根。 前序遍历&#xff1a;做题入口 class Solution {public List<Integer> preorderTraversal(TreeNode root) {List<Integer…

求分享如何批量压缩视频的容量的方法

视频内存过大&#xff0c;不但特别占内存&#xff0c;而且还会使手机电脑出现卡顿的现象&#xff0c;除此之外&#xff0c;如果我们想发送这些视频文件可能还会因为内存太大无法发送。因此&#xff0c;我们可以批量地压缩视频文件的内存大小&#xff0c;今天小编要来分享一招&a…

VSCode配置之C++ SQLite3极简配置方案

背景 最近在学习《深入应用C11: 代码优化与工程级应用》&#xff0c;其中第13章说到SQLite库&#xff0c;查询网上诸多教程&#xff0c;发现比较容易出现bug且配置较为麻烦&#xff0c;故记录此次简化版方案&#xff0c;以供参考。 软件环境 SQLite 3.42.0 版本&#xff08;仅…

解读分布式锁(redis实现方案)

1.导读 分布式锁是一种用于分布式系统中的并发控制机制&#xff0c;它用于确保在多个节点或多个进程之间的并发操作中&#xff0c;某些关键资源或代码块只能被一个节点或进程同时访问。分布式锁的目的是避免多个节点同时修改共享资源而导致的数据不一致或冲突的问题。通俗的来…

【MySQL】索引与B+树

【MySQL】索引与B树 索引概念前导硬件软件方面 索引的理解单个page多个page引入B树B树的特征为什么B树做索引优于其他数据结构&#xff1f;聚簇索引与非聚簇索引辅助索引 索引的创建主键索引的创建和查看唯一键索引的创建和查看普通索引的创建和查看复合索引全文索引索引的其他…

【数据集】3小时尺度降水数据集-MSWEPV2

1 MSWEP V2 precipitation product 官网-MSWEP V2降水产品 参考

【Python数据分析】Python基本数据类型

&#x1f389;欢迎来到Python专栏~Python基本数据类型 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;Python学习专栏 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0c;希望…

基于WSL2、Ubuntu和VS Code的CUDA平台运行C语言程序

一、CUDA程序执行方法 执行步骤为&#xff1a; 安装Visual Studio Code。在Visual Studio Code中安装插件WSL与电脑的WSL2进行连接。点击左下角&#xff0c;然后再选择连接到WSL。 在WSL中创建以 .cu 为后缀的文件。 rootDESKTOP-HR6VO5J:~# mkdir CUDA /…

Flutter ios真机调试连接断开后应用闪退

使用ios真机调试的时候&#xff0c;能正常打开应用&#xff0c;但是当数据线断开连接的时候&#xff0c;应用就会关闭&#xff0c;重新打开就会闪退。 原因是flutter默认在开发过程中使用debug模式编译 只需要将debug选择为release 重新编译就行。

C++代码格式化工具clang-format详细介绍

文章目录 clang-format思考代码风格指南生成您的配置运行 clang-format禁用一段代码的格式设置clang-format的设置预览 clang-format 我曾在许多编程团队工作过&#xff0c;这些团队名义上都有“编程风格指南”。该指南经常被写下来并放置在开发人员很少查看的地方。几乎在每种…

Shell 排序法 - 改良的插入排序

说明 插入排序法由未排序的后半部前端取出一个值&#xff0c;插入已排序前半部的适当位置&#xff0c;概念简单但速度不快。 排序要加快的基本原则之一&#xff0c;是让后一次的排序进行时&#xff0c;尽量利用前一次排序后的结果&#xff0c;以加快排序的速度&#xff0c;Shel…

【软件测试】基于博客系统的自动化测试

目录 1.我的博客系统链接 2.使用selenium对博客系统进行自动化测试 1.引入依赖 2.创建公共类 3.创建测试套件类 4.测试登陆界面 5. 测试博客列表页 6.测试写博客页面 7.测试删除博客 8.最终运行结果 1.我的博客系统链接 用户登录 2.使用selenium对博客系统进行自动…

Git时间:版本控制工具进阶

Git时间&#xff1a;版本控制工具进阶 忽略文件 Git允许用户将指定的文件或目录排除在版本控制之外&#xff0c;它会检查代码仓库的目录下是否存在一个名为.gitignore的文件&#xff0c;如果存在&#xff0c;就去一行行读取这个文件中的内容&#xff0c;并把每一行指定的文件…

【算法和数据结构】257、LeetCode二叉树的所有路径

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;首先看这道题的输出结果&#xff0c;是前序遍历。然后需要找到从根节点到叶子节点的所有路径&#xff…