轻松提高性能和并发度,springboot简单几步集成缓存

Posted 香菜+

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了轻松提高性能和并发度,springboot简单几步集成缓存相关的知识,希望对你有一定的参考价值。

目录

1、缘由

2、技术介绍

2.1、技术调研

2.2、spring支持的cache

2.3、cache的核心注解

 2.3.1 @EnableCaching

2.3.2 @Cacheable

 2.3.3 @CachePut

2.3.4 @CacheEvict 

2.4 cache的架构

2.5 cachemanager的实现类

3、搞个例子

3.1 为什么使用redis 作为缓存

3.2 代码走起

3.2.1 创建一个web项目

3.2.2 配置redis

3.2.3 配置cachemanager

3.2.4 使用注解 

4、总结


1、缘由

        做游戏的时候是公司自己做的缓存,而且是公司的祖传代码,做的相当难用,这是每个刚入职的同学最搞不清楚的状况,稍微做不好就会丢失数据,这个也是之前一直存在的问题,但是为了项目的稳定,也没人敢去动那坨祖传代码,毕竟能跑就行,要什么自行车。

        在重返web之后,发现现在的技术栈是真的方便,各种轮子,只要你想就会有相应的轮子,而且做的极其好用,最近新项目要启动了,之前做的并发一直不大,也没考虑什么缓存和性能,后面说是大项目,先做一些调研。今天就聊下springboot的缓存。

2、技术介绍

2.1、技术调研

        作为Javaer,web开发离不开springboot,但是缓存的策略一直没有定,所以看下springboot的缓存机制,这个过程几乎没有什么可选的,毕竟其他的做起来太麻烦了。选型主要是在是否需要使用外置的缓存,也就是是否使用redis

2.2、spring支持的cache

`Spring Cache 是Spring 提供的一整套的缓存解决方案,它不是具体的缓存实现,它只提供一整套的接口和代码规范、配置、注解等,用于整合各种缓存方案,比如Caffeine、Guava Cache、Ehcache,Redis等

2.3、cache的核心注解

 2.3.1 @EnableCaching

@EnableCaching注解是spring framework中的注解驱动的缓存管理功能。

当你在配置类上使用@EnableCaching注解时,会触发一个post processor,这会扫描每一个spring bean,查看是否已经存在注解对应的缓存。如果找到了,就会自动创建一个代理拦截方法调用,使用缓存的bean执行处理。

注:一般放在application类上

2.3.2 @Cacheable

@Cacheable 注解在方法上,表示该方法的返回结果是可以缓存的。 也就是说,该方法的返回结果会放在缓存中,以便于以后使用相同的参数调用该方法时,会返回缓存中的值,而不会实际执行该方法。

  注意:参数相同。这一点应该是很容易理解的,因为缓存不关心方法的执行逻辑,它能确定的是:对于同一个方法,如果参数相同,那么返回结果也是相同的。

注: 一般使用在查询方法上

 2.3.3 @CachePut

        使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库。

注:一般用在新增和修改的方法上

2.3.4 @CacheEvict 

使用该注解标志的方法,会清空指定的缓存。

2.4 cache的架构

 这张图太经典了,在网上搜到最多的就是这个了,已经表达的很好了,这里一定要拿过来。

2.5 cachemanager的实现类

 这个图也是来自网上,可以看到是很多的不同cache的实现类,在使用的时候需要在项目中导入相应的包,没毛病。

3、搞个例子

说再多没啥用,毕竟都是理论,是骡子是马拉出来溜溜,整点实际的,搞个项目吧。

3.1 为什么使用redis 作为缓存

springboot内置的cache是内存缓存,很好,但是我这里选择了redis测试,也是因为项目中想要使用redis,主要理由有几条:

1.cache 内存掉电会丢失,redis还在(不致命,毕竟是缓存)

2.redis支持分布式,在多个app的时候可以共享缓存(优势点)

3.redis支持的数据类型更多

3.2 代码走起

3.2.1 创建一个web项目

这里就不赘述了,主要是pom.xml

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.6.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

包很简单,应该没啥毛病

3.2.2 配置redis

spring:
  cache:
    type: redis
  redis:
    database: 8
    host: 172.26.1.152
    port: 6379
    timeout: 1800000

3.2.3 配置cachemanager


import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.*;
import java.time.Duration;

/**
 * Redis 配置类
 */
@Configuration
@EnableCaching //开启缓存配置
public class RedisConfig 

    /**
     * 配置缓存管理器
     * @param factory Redis 线程安全连接工厂
     * @return 缓存管理器
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) 
        // 生成两套默认配置,通过 Config 对象即可对缓存进行自定义配置
        RedisCacheConfiguration cacheConfig1 = RedisCacheConfiguration.defaultCacheConfig()
                // 设置过期时间 10 分钟
                .entryTtl(Duration.ofMinutes(10))
                // 禁止缓存 null 值
                .disableCachingNullValues()
                // 设置 key 序列化
                .serializeKeysWith(keyPair())
                // 设置 value 序列化
                .serializeValuesWith(valuePair());
        // 返回 Redis 缓存管理器
        return RedisCacheManager.builder(factory)
                .withCacheConfiguration("aa", cacheConfig1)
                .build();
    

    /**
     * 配置键序列化
     */
    private RedisSerializationContext.SerializationPair<String> keyPair() 
        return RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer());
    

    /**
     * 配置值序列化,使用 GenericJackson2JsonRedisSerializer 替换默认序列化
     */
    private RedisSerializationContext.SerializationPair<Object> valuePair() 
        return RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer());
    



3.2.4 使用注解 

@Service
public class TimeService 
    @Cacheable(cacheNames = "curTime" ,key = "#key ")
    public Long getCurrentTime(String key)
        long l = System.currentTimeMillis();
        System.err.println("当前时间 : "+ l);
        return l;
    

这里使用了cacheable ,这里的key 是传进来的参数,看下redis中的数据

注意:重启程序缓存依然还在,缓存在调用方法时会先去redis确认数据是否存在,如果不存在才会调用方法,存在的话则直接从redis取值。

4、总结

springboot集成缓存是真的方便,简单几步就搞定了,这在开发中已经够用了,当然每个技术都有自己的犄角旮旯,在使用的时候多踩几次坑就知道了。

写作是无聊的,沟通交流才是需求,希望能得到双向的交流,点赞和评论是最好的赞美

 

以上是关于轻松提高性能和并发度,springboot简单几步集成缓存的主要内容,如果未能解决你的问题,请参考以下文章

翻译只需几步,轻松提高Typescript性能

简单几步,设计一个高性能的秒杀系统!

Java 并发编程实践

大型php网站性能和并发访问优化方案

微信分享视频不能大于25M?其实这样简单操作几步,就能轻松发送

Nginx神来之笔,提高并发原来如此简单