Spring Boot 缓存应用实践

这篇具有很好参考价值的文章主要介绍了Spring Boot 缓存应用实践。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

缓存是最直接有效提升系统性能的手段之一。个人认为用好用对缓存是优秀程序员的必备基本素质。本文结合实际开发经验,从简单概念原理和代码入手,一步一步搭建一个简单的二级缓存系统。

一、通用缓存接口

1、缓存基础算法

  • FIFO(First In First Out),先进先出,和OS里的FIFO思路相同,如果一个数据最先进入缓存中,当缓存满的时候,应当把最先进入缓存的数据给移除掉。

  • LFU(Least Frequently Used),最不经常使用,如果一个数据在最近一段时间内使用次数很少,那么在将来一段时间内被使用的可能性也很小。

  • LRU(Least Recently Used),最近最少使用,如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据移除。

2、接口定义

简单定义缓存接口,大致可以抽象如下:

package com.power.demo.cache.contract;

import java.util.function.Function;

/**
 * 缓存提供者接口
 **/
public interface CacheProviderService {

    /**
     * 查询缓存
     *
     * @param key 缓存键 不可为空
     **/
    <T extends Object> T get(String key);

    /**
     * 查询缓存
     *
     * @param key 缓存键 不可为空
     * @param function 如没有缓存,调用该callable函数返回对象 可为空
     **/
    <T extends Object> T get(String key, Function<String, T> function);

    /**
     * 查询缓存
     *
     * @param key 缓存键 不可为空
     * @param function 如没有缓存,调用该callable函数返回对象 可为空
     * @param funcParm function函数的调用参数
     **/
    <T extends Object, M extends Object> T get(String key, Function<M, T> function, M funcParm);

    /**
     * 查询缓存
     *
     * @param key 缓存键 不可为空
     * @param function 如没有缓存,调用该callable函数返回对象 可为空
     * @param expireTime 过期时间(单位:毫秒) 可为空
     **/
    <T extends Object> T get(String key, Function<String, T> function, Long expireTime);

    /**
     * 查询缓存
     *
     * @param key 缓存键 不可为空
     * @param function 如没有缓存,调用该callable函数返回对象 可为空
     * @param funcParm function函数的调用参数
     * @param expireTime 过期时间(单位:毫秒) 可为空
     **/
    <T extends Object, M extends Object> T get(String key, Function<M, T> function, M funcParm, Long expireTime);

    /**
     * 设置缓存键值
     *
     * @param key 缓存键 不可为空
     * @param obj 缓存值 不可为空
     **/
    <T extends Object> void set(String key, T obj);

    /**
     * 设置缓存键值
     *
     * @param key 缓存键 不可为空
     * @param obj 缓存值 不可为空
     * @param expireTime 过期时间(单位:毫秒) 可为空
     **/
    <T extends Object> void set(String key, T obj, Long expireTime);

    /**
     * 移除缓存
     *
     * @param key 缓存键 不可为空
     **/
    void remove(String key);

    /**
     * 是否存在缓存
     *
     * @param key 缓存键 不可为空
     **/
    boolean contains(String key);
}

注意,这里列出的只是常见缓存功能接口,一些在特殊场景下用到的统计类的接口、分布式锁、自增(减)等功能不在讨论范围之内。

Get相关方法,注意多个参数的情况,缓存接口里面传人的Function,这是Java8提供的函数式接口,虽然支持的入参个数有限(这里你会非常怀念.NET下的Func委托),但是仅对Java这个语言来说,这真是一个重大的进步^_^。

接口定义好了,下面就要实现缓存提供者程序了。按照存储类型的不同,本文简单实现最常用的两种缓存提供者:本地缓存和分布式缓存

二、本地缓存

本地缓存,也就是JVM级别的缓存(本地缓存可以认为是直接在进程内通信调用,而分布式缓存则需要通过网络进行跨进程通信调用),一般有很多种实现方式,比如直接使用Hashtable、ConcurrentHashMap等天生线程安全的集合作为缓存容器,或者使用一些成熟的开源组件,如EhCache、Guava Cache等。本文选择上手简单的Guava缓存。

1、什么是Guava

Guava,简单来说就是一个开发类库,且是一个非常丰富强大的开发工具包,号称可以让使用Java语言更令人愉悦,主要包括基本工具类库和接口、缓存、发布订阅风格的事件总线等。在实际开发中,我用的最多的是集合、缓存和常用类型帮助类,很多人都对这个类库称赞有加。文章来源地址https://www.toymoban.com/news/detail-534105.html

2、添加依赖

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
</dependency>

3、实现接口

/*
 * 本地缓存提供者服务 (Guava Cache)
 * */
@Configuration
@ComponentScan(basePackages = AppConst.BASE_PACKAGE_NAME)
@Qualifier("localCacheService")
public class LocalCacheProviderImpl implements CacheProviderService {

    private static Map<String, Cache<String, Object>> _cacheMap = Maps.newConcurrentMap();

    static {

        Cache<String, Object> cacheContainer = CacheBuilder.newBuilder()
                .maximumSize(AppConst.CACHE_MAXIMUM_SIZE)
                .expireAfterWrite(AppConst.CACHE_MINUTE, TimeUnit.MILLISECONDS)//最后一次写入后的一段时间移出
                //.expireAfterAccess(AppConst.CACHE_MINUTE, TimeUnit.MILLISECONDS) //最后一次访问后的一段时间移出
                .recordStats()//开启统计功能
                .build();

        _cacheMap.put(String.valueOf(AppConst.CACHE_MINUTE), cacheContainer);
    }

    /**
     * 查询缓存
     *
     * @param key 缓存键 不可为空
     **/
    public <T extends Object> T get(String key) {
        T obj = get(key, null, null, AppConst.CACHE_MINUTE);

        return obj;
    }

    /**
     * 查询缓存
     *
     * @param key 缓存键 不可为空
     * @param function 如没有缓存,调用该callable函数返回对象 可为空
     **/
    public <T extends Object> T get(String key, Function<String, T> function) {
        T obj = get(key, function, key, AppConst.CACHE_MINUTE);

        return obj;
    }

    /**
     * 查询缓存
     *
     * @param key 缓存键 不可为空
     * @param function 如没有缓存,调用该callable函数返回对象 可为空
     * @param funcParm function函数的调用参数
     **/
    public <T extends Object, M extends Object> T get(String key, Function<M, T> function, M funcParm) {
        T obj = get(key, function, funcParm, AppConst.CACHE_MINUTE);

        return obj;
    }

    /**
     * 查询缓存
     *
     * @param key 缓存键 不可为空
     * @param function 如没有缓存,调用该callable函数返回对象 可为空
     * @param expireTime 过期时间(单位:毫秒) 可为空
     **/
    public <T extends Object> T get(String key, Function<String, T> function, Long expireTime) {
        T obj = get(key, function, key, expireTime);

        return obj;
    }

    /**
     * 查询缓存
     *
     * @param key 缓存键 不可为空
     * @param function 如没有缓存,调用该callable函数返回对象 可为空
     * @param funcParm function函数的调用参数
     * @param expireTime 过期时间(单位:毫秒) 可为空
     **/
    public <T extends Object, M extends Object> T get(String key, Function<M, T> function, M funcParm, Long expireTime) {
        T obj = null;
        if (StringUtils.isEmpty(key) == true) {
            return obj;
        }

        expireTime = getExpireTime(expireTime);

        Cache<String, Object> cacheContainer = getCacheContainer(expireTime);

        try {
            if (function == null) {
                obj = (T) cacheContainer.getIfPresent(key);
            } else {
                final Long cachedTime = expireTime;
                obj = (T) cacheContainer.get(key, () -> {
                    T retObj = 

到了这里,关于Spring Boot 缓存应用实践的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • “深入理解Spring Boot:构建独立、可扩展的企业级应用程序的最佳实践“

    标题:深入理解Spring Boot:构建独立、可扩展的企业级应用程序的最佳实践 摘要:Spring Boot是一个强大的框架,可以帮助开发人员快速构建独立、可扩展的企业级应用程序。本文将深入探讨Spring Boot的核心概念和最佳实践,并通过示例代码演示其用法。 正文: 什么是Spring Bo

    2024年02月14日
    浏览(60)
  • 解锁Spring Boot中的设计模式—04.桥接模式:探索【桥接模式】的奥秘与应用实践!

    桥接模式也称为桥梁模式、接口模式或者柄体(Handle and Body)模式,是将 抽象部分 与他的 具体实现部分 分离 ,使它们都可以独立地变化,通过 组合 的方式 建立 两个类之间的 联系 ,而不是继承。 桥接模式是一种结构型设计模式,旨在将抽象部分与实现部分分离,使它们

    2024年02月21日
    浏览(52)
  • 解锁Spring Boot中的设计模式—03.委派模式:探索【委派模式】的奥秘与应用实践!

    委派模式 是一种负责任务的调度和分配模式,类似于代理模式但更注重结果而非过程。它可以被视为一种特殊情况下的静态代理的全权代理,但并不属于GOF 23种设计模式之一,而是归类为行为型模式。 委派模式在Spring框架中广泛应用,其中最常见的例子是 DispatcherServlet ,它

    2024年02月19日
    浏览(54)
  • Spring Boot进阶(67):高性能缓存!使用Spring Boot轻松集成Memcached。

            Memcached是一款高性能的分布式内存对象缓存系统,主要用于动态Web应用中减轻数据库负载。Spring Boot是一款基于Spring框架的快速开发框架,集成了大量的常用技术和组件,方便开发者快速搭建项目。将两者结合起来,可以提高Web应用的性能,并减少数据库的压力。

    2024年02月07日
    浏览(63)
  • 解锁Spring Boot中的设计模式—02.解释器模式:探索【解释器模式】的奥秘与应用实践!

    解释器模式(Interpreter Pattern)是一种行为设计模式,它用于定义语言的文法,并且解释语言中的表达式。在Java中,解释器模式可以用于构建解释器以解析特定的语言或表达式,如数学表达式、查询语言等。 优点: 灵活性: 解释器模式可以 灵活地添加新的表达式和规则 ,因

    2024年02月19日
    浏览(69)
  • Spring Boot多级缓存实现方案

    1.背景 缓存,就是让数据更接近使用者,让访问速度加快,从而提升系统性能。工作机制大概是先从缓存中加载数据,如果没有,再从慢速设备(eg:数据库)中加载数据并同步到缓存中。 所谓多级缓存,是指在整个系统架构的不同系统层面进行数据缓存,以提升访问速度。主要

    2024年02月14日
    浏览(35)
  • Spring Boot 缓存 Cache 入门

    在系统访问量越来越大之后,往往最先出现瓶颈的往往是数据库。而为了减少数据库的压力, 我们可以选择让产品砍掉消耗数据库性能的需求 。 当然也可以引入缓存,在引入缓存之后,我们的读操作的代码,往往代码如下: 这段代码,是比较常用的缓存策略,俗称**“被动写

    2024年02月15日
    浏览(52)
  • 【Spring Boot】深入解密Spring Boot日志:最佳实践与策略解析

    💓 博客主页:从零开始的-CodeNinja之路 ⏩ 收录文章:【Spring Boot】深入解密Spring Boot日志:最佳实践与策略解析 🎉欢迎大家点赞👍评论📝收藏⭐文章 日志对我们来说并不陌⽣,通过打印日志来发现和定位问题,或者根据日志来分析程序的运行过程. 日志的用途 Spring Boot中的日

    2024年04月17日
    浏览(48)
  • 【Spring Boot】缓存预热与缓存清除--原理、作用和目的

    在本文中,我们将详细讲解两个与缓存相关的重要概念: 缓存预热 和 缓存清除 。 我们将了解缓存的基本概念,然后分别介绍缓存预热和缓存清除的原理、作用和目的。 缓存是一种数据存储技术,用于存储经常访问的数据,以便在需要时快速获取 。通过缓存数据,可以 减

    2023年04月21日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包