Spring Boot整合Redis实现缓存操作(工程代码实现).md


  1. 缓存的应用场景
  • 什么是缓存?
在互联网场景下,尤其 2C 端大流量场景下,需要将一些经常展现和不会频繁变更的数据,存放在存取速率更快的地方。缓存就是一个存储器,在技术选型中,常用 Redis 作为缓存数据库。缓存主要是在获取资源方便性能优化的关键方面。

Redis 是一个高性能的 key-value 数据库。
  • 缓存的应用场景有哪些呢?
比如常见的电商场景,根据商品 ID 获取商品信息时,店铺信息和商品详情信息就可以缓存在 Redis,直接从 Redis 获取。减少了去数据库查询的次数。但会出现新的问题,就是如何对缓存进行更新?
  1. 更新缓存的策略
  • 缓存更新的模式有四种:Cache aside, Read through, Write through, Write behind caching
使用Cache aside策略,从三个维度:
失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。
命中:应用程序从cache中取数据,取到后返回。
更新:先把数据存到数据库中,成功后,再让缓存失效。
  • 大致流程如下:
获取商品详情举例:
a. 从商品 Cache 中获取商品详情,如果存在,则返回获取 Cache 数据返回。
b. 如果不存在,则从商品 DB 中获取。获取成功后,将数据存到 Cache 中。则下次获取商品详情,就可以从 Cache 就可以得到商品详情数据。
c. 从商品 DB 中更新或者删除商品详情成功后,则从缓存中删除对应商品的详情缓存

在这里插入图片描述

  1. pom.xml依赖配置:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>springboot</groupId>
    <artifactId>springboot-mybatis-redis</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-mybatis-redis :: 整合 Mybatis 并使用 Redis 作为缓存</name>
 
    <!-- Spring Boot 启动父依赖 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.1.RELEASE</version>
    </parent>
 
    <properties>
        <mybatis-spring-boot>1.2.0</mybatis-spring-boot>
        <mysql-connector>5.1.39</mysql-connector>
        <spring-boot-starter-redis-version>1.3.2.RELEASE</spring-boot-starter-redis-version>
    </properties>
 
    <dependencies>
 
        <!-- Spring Boot Reids 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-redis</artifactId>
            <version>${spring-boot-starter-redis-version}</version>
        </dependency>
 
        <!-- Spring Boot Web 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
 
        <!-- Spring Boot Test 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
 
        <!-- Spring Boot Mybatis 依赖 -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis-spring-boot}</version>
        </dependency>
 
        <!-- MySQL 连接驱动依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql-connector}</version>
        </dependency>
 
        <!-- Junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
</project>
  1. application.properties 应用配置文件,增加 Redis 相关配置:
## 数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/springbootdb?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=980414
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

## Mybatis 配置
mybatis.typeAliasesPackage=org.spring.springboot.domain
mybatis.mapperLocations=classpath:mapper/*.xml

## Redis 配置
## Redis数据库索引(默认为0)
spring.redis.database=0
## Redis服务器地址
spring.redis.host=localhost
## Redis服务器连接端口
spring.redis.port=6379
## Redis服务器连接密码(默认为空)
spring.redis.password=
## 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
## 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
## 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
## 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
## 连接超时时间(毫秒)
spring.redis.timeout=0
  1. 业务逻辑实现类CityServiceImpl.java:
/**
 * 城市业务逻辑实现类
 * <p>
 * Created by bysocket on 07/02/2017.
 */
@Service
public class CityServiceImpl implements CityService {
 
    private static final Logger LOGGER = LoggerFactory.getLogger(CityServiceImpl.class);
 
    @Autowired
    private CityDao cityDao;
 
    @Autowired
    private RedisTemplate redisTemplate;
 
    /**
     * 获取城市逻辑:
     * 如果缓存存在,从缓存中获取城市信息
     * 如果缓存不存在,从 DB 中获取城市信息,然后插入缓存
     */
    public City findCityById(Long id) {
        // 从缓存中获取城市信息
        String key = "city_" + id;
        ValueOperations<String, City> operations = redisTemplate.opsForValue();
 
        // 缓存存在
        boolean hasKey = redisTemplate.hasKey(key);
        if (hasKey) {
            City city = operations.get(key);
 
            LOGGER.info("CityServiceImpl.findCityById() : 从缓存中获取了城市 >> " + city.toString());
            return city;
        }
 
        // 从 DB 中获取城市信息
        City city = cityDao.findById(id);
 
        // 插入缓存
        operations.set(key, city, 10, TimeUnit.SECONDS);
        LOGGER.info("CityServiceImpl.findCityById() : 城市插入缓存 >> " + city.toString());
 
        return city;
    }
 
    @Override
    public Long saveCity(City city) {
        return cityDao.saveCity(city);
    }
 
    /**
     * 更新城市逻辑:
     * 如果缓存存在,删除
     * 如果缓存不存在,不操作
     */
    @Override
    public Long updateCity(City city) {
        Long ret = cityDao.updateCity(city);
 
        // 缓存存在,删除缓存
        String key = "city_" + city.getId();
        boolean hasKey = redisTemplate.hasKey(key);
        if (hasKey) {
            redisTemplate.delete(key);
 
            LOGGER.info("CityServiceImpl.updateCity() : 从缓存中删除城市 >> " + city.toString());
        }
 
        return ret;
    }
 
    @Override
    public Long deleteCity(Long id) {
 
        Long ret = cityDao.deleteCity(id);
 
        // 缓存存在,删除缓存
        String key = "city_" + id;
        boolean hasKey = redisTemplate.hasKey(key);
        if (hasKey) {
            redisTemplate.delete(key);
 
            LOGGER.info("CityServiceImpl.deleteCity() : 从缓存中删除城市 ID >> " + id);
        }
        return ret;
    }
 
}
  • 首先这里注入了RedisTemplate对象。联想到Spring的JdbcTemplate,RedisTemplate封装了RedisConnection,具有连接管理,序列化和Redis操作等功能。还有针对String的支持对象StringRedisTemplate。
  • Redis 操作视图接口类用的是ValueOperations,对应的是Redis String/Value操作。还有其他的操作视图,ListOperations、SetOperations、ZSetOperations和HashOperations。ValueOperations插入缓存是可以设置失效时间,这里设置的失效时间是10s。
  • 回到更新缓存的逻辑:
a. findCityById 获取城市逻辑:
如果缓存存在,从缓存中获取城市信息
如果缓存不存在,从 DB 中获取城市信息,然后插入缓存
b. deleteCity 删除城市逻辑 / updateCity 更新城市逻辑:
如果缓存存在,删除
如果缓存不存在,不操作

参考:https://www.bysocket.com/?page_id=1639

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值