Skip to content

Redis 缓存

简介

应用程序都要从数据库里存取数据,在集群环境中,数据库的压力很大,在应用层增加缓存能极大地减轻数据库的负担,提高系统的响应能力。从 3.1 开始,Spring 引入了对 Cache 的支持。其使用方法和原理都类似于Spring对事务管理的支持。Spring Cache 是作用在方法上的,其核心思想是这样的:当我们在调用一个缓存方法时会把该方法参数和返回结果作为一个键值对存放在缓存中,等到下次利用同样的参数来调用该方法时将不再执行该方法,而是直接从缓存中获取结果进行返回。所以在使用 Spring Cache 的时候我们要保证我们缓存的方法对于相同的方法参数要有相同的返回结果。

Spring 自身不提供缓存的存储实现,需要借助第三方,例如:EhCache 2.x、Hazelcast、Infinispan、Redis、Guava、Simple 等技术进行缓存实现。

Y9 主要采用的是基于 Redis 作为缓存载体的技术实现。

功能引用

(1)修改pom.xml

  • 将本公司的私服仓库地址添加到pom.xml文件中。
xml
 <repositories>
    <repository>
        <id>y9-internet-repo</id>
        <url>https://svn.youshengyun.com:9900/nexus/repository/maven-public/</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
            <!-- <updatePolicy>always</updatePolicy> -->
            <!-- always,daily(default),interval:XXX,never -->
        </snapshots>
    </repository>
</repositories>
  • 将 risenet-y9boot-starter-cache-redis 添加至依赖中:
xml
<dependency>
    <groupId>net.risesoft</groupId>
    <artifactId>risenet-y9boot-starter-cache-redis</artifactId>
    <version>[最新版本]</version>
</dependency>
  • 引入 aspectj 依赖包。
xml
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
</dependency>
  • 在 plugins 中引入 aspectj-maven-plugin。
xml
 <build>
    <plugins>
        <plugin>
            <groupId>dev.aspectj</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

如若 parent 不是数字底座的根 pom.xml,则需在 properties 中添加 jdk 和 aspectj 的版本属性,

xml
<properties>
    <java.version>11</java.version> 
    <aspectj.version>1.9.20.1</aspectj.version>
    <aspectj-maven-plugin.version>1.13.1</aspectj-maven-plugin.version>
</properties>

在 build > plugins 中添加一下依赖:

xml
<plugin>
    <!--<groupId>com.nickwongdev</groupId>-->
    <groupId>dev.aspectj</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>${aspectj-maven-plugin.version}</version>
    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
    </dependencies>
    <executions>
        <execution>
            <id>weave-classes</id>
            <phase>process-classes</phase>
            <goals>
                <goal>compile</goal>
            </goals>
            <configuration>
                <sources/>
                <weaveDirectories>
                    <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
                </weaveDirectories>
            </configuration>
        </execution>
        <execution>
            <id>weave-test-classes</id>
            <phase>process-test-classes</phase>
            <goals>
                <goal>test-compile</goal>
            </goals>
            <configuration>
                <testSources/>
                <weaveDirectories>
                    <weaveDirectory>${project.build.directory}/test-classes</weaveDirectory>
                </weaveDirectories>
            </configuration>
        </execution>
    </executions>
    <configuration>
        <verbose>true</verbose>
        <forceAjcCompile>true</forceAjcCompile>
        <aspectLibraries>
            <aspectLibrary>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
            </aspectLibrary>
        </aspectLibraries>
        <complianceLevel>${java.version}</complianceLevel>
        <source>${java.version}</source>
        <target>${java.version}</target>
        <encoding>UTF-8</encoding>
        <showWeaveInfo>true</showWeaveInfo>
    </configuration>
</plugin>

(2)修改属性文件

properties
y9.common.cacheEnabled=true

spring.redis.database=8
spring.redis.host=218.60.41.112
spring.redis.password=y9i-83204585
spring.redis.port=6379
spring.redis.ssl=false
spring.redis.timeout=10000
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.max-wait=-1
spring.redis.lettuce.pool.min-idle=0
spring.redis.lettuce.shutdown-timeout=100ms
spring.data.redis.repositories.enabled=false

spring.cache.redis.time-to-live=PT2H
spring.cache.type=redis
#可以不写
spring.cache.cache-names=
yaml
spring:
    cache:
        redis:
            time-to-live: PT2H
        type: redis
    data:
        redis:
            repositories:
                enabled: false
    redis:
        database: 8
        host: localhost
        lettuce:
            pool:
                max-active: 8
                max-idle: 8
                max-wait: -1
                min-idle: 0
            shutdown-timeout: 100ms
        password: y9i-83204585
        port: 6379
        ssl: false
        timeout: 10000
y9:
    common:
        cacheEnabled: true

(3)代码示例

package net.risesoft.example.service.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import net.risesoft.example.entity.User;
import net.risesoft.example.repository.UserRepository;
import net.risesoft.example.service.UserService;
import net.risesoft.id.Y9IdGenerator;

/**
 * 描述:人员 服务实现层
 */
@Service(value = "userService")
@CacheConfig(cacheNames = "y9cache_User")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    @Cacheable(key = "#id", condition = "#id!=null", unless = "#result==null")
    public User findById(String id) {
        return userRepository.findById(id).orElse(null);
    }

    @Override
    @CacheEvict(key = "#id")
    public void deleteById(String id) {
        Optional<User> user = userRepository.findById(id);
        if (user.isPresent()) {
            userRepository.deleteById(id);
        }
    }

    @Override
    @CacheEvict(key = "#user.id")
    public User saveOrUpdate(User user) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        User u = new User();
        if (StringUtils.isBlank(user.getId())) {
            u.setId(Y9IdGenerator.genId());
            u.setCreateTime(sdf.format(new Date()));
        } else {
            u = userRepository.findById(user.getId()).orElse(null);
        }
        u.setName(user.getName());
        u.setAge(user.getAge());
        u.setBirth(user.getBirth());
        u.setEducation(user.getEducation());
        u.setMobile(user.getMobile());
        u.setSex(user.getSex());
        return userRepository.save(u);

    }

    @Override
    @CacheEvict(key = "#user.id")
    public User save(User user) {
        return userRepository.save(user);
    }

    @Override
    public List<User> findAll() {
        return userRepository.findAll();
    } 

}

其中:

@EnableCaching:开启缓存,

@Cacheable:保存缓存的注解,方法结果会被放入缓存,并且一旦缓存后,下一次调用此方法,会通过key去查找缓存是否存在,如果存在就直接取缓存值,不再执行方法。方法执行前先看缓存中是否有数据,如果有直接返回。如果没有就调用方法,并将方法返回值放入缓存

@CacheEvict:删除缓存的注解,标记的方法会在方法执行前或者执行后移除Spring Cache中的某些元素。设置allEntries=true时,可以对整个条目进行批量删除。

注:为保持缓存数据的一致性,在对实例对象进行修改和删除操作之前要先将数据从缓存中移除。即在方法上添加@CacheEvict注解。

示例代码

码云地址:https://gitee.com/risesoft-y9/y9-core

该示例代码路径地址:https://gitee.com/risesoft-y9/y9-core/tree/main/y9-digitalbase-example/risenet-y9demo-cache

Released under the GPL-3.0 License.