Spring-Boot-2x十四整合Redis看这一篇就够了

5次阅读

共计 4709 个字符,预计需要花费 12 分钟才能阅读完成。

[TOC]

Redis 简介

Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可 基于内存亦可持久化 的日志型、Key-Value 数据库,并提供 多种语言的 API 非关系型数据库(NoSQL)

Redis 的特性

  1. Redis 的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过 MULTI 和 EXEC 指令包起来。
  2. 性能极高 – Redis 能读的速度是 110000 次 /s, 写的速度是 81000 次 /s。丰富的数据类型 – Redis 支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  3. 原子 – Redis 的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过 MULTI 和 EXEC 指令包起来。
  4. 丰富的特性 – Redis 还支持 publish/subscribe, 通知, key 过期等等特性。

Redis 的应用

  1. 会话缓存
  2. 数据缓存
  3. 排行榜 / 计数器
  4. 消息队列

Redis 的数据类型

  • String: 字符串
  • Hash: 散列
  • List: 列表
  • Set: 集合
  • Sorted Set: 有序集合

Redis 的部署

PS: 我这里是基于 Mac 环境,Windows 环境下的同学可以安装 Linux 虚拟机同步进行操作。

  1. 官网下载 Stable(稳定)版本

  1. 找到下载的文件,解压并编译
tar -zxvf redis-5.0.4.tar.gz
mv redis-5.0.4 /usr/local/
cd /usr/local/redis-5.0.4/
make test

执行到这里,最好先执行一遍 make test,确保编译可以通过,需要大概三分钟。
到这个就说明测试通过了。我们接着往下执行

make
cd src/
make install

执行到这里安装就算是告一段落了,接下来我们进行 redis 的一些配置:

vim ../redis.conf

找到 136 行左右的 daemonize 将其属性改为 yes,可以让 redis 在后台运行,然后找到 500 行左右的 requirepass,后面输入我们需要设置的密码,这样就可以通过密码来访问 redis 了。
然后我们通过指定配置文件的方式来启动 redis

./redis-server ../redis.conf

执行完事儿之后,查看是否执行成功:

ps -ef | grep redis

可以看到,我们的 redis 已经启动成功了,然后通过 rdm 来访问一下:

大功告成,现在万事俱备,只欠东风。我们下面来看一下在 Spring Boot 中怎么使用 redis 吧。

在 Spring Boot 中的使用

Spring Boot 给我们提供了现成的spring-boot-starter-data-redis,我们只需要在 pom 文件中将之导入即可。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- 创建连接池 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

然后,我们需要在配置文件中配置一些有关 redis 的信息:

spring:
  redis:
    host: 127.0.0.1  # IP
    port: 6379  # 端口号
    password: 123456  # 密码
    lettuce:
      pool:
        max-active: 8 # 连接池最大连接数
        max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)min-idle: 0 # 连接池中的最小空闲连接
        max-idle: 8 # 连接池中的最大空闲连接

接下来,我们需要对我们所需要的 Redis 的操作给封装到一个接口中,方便我们去调用,这里我基于接口,抽象类,实现类的结构实现了一套 Redis 的方法,需要的同学可以去 GitHub 上下载(子项目名称:viboot-rds),GitHub 的地址在文末。这里仅仅贴出接口的 部分方法

package com.itframe.dao;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 *
 */
public interface RedisDao {

    /**
     * 判断缓存中是否有对应的 value
     * 
     * @param key
     * @return boolean
     */
    public boolean existsKey(Object key);

    /**
     * 根据 key 获取 key 列表(key 值可为模糊匹配 ---taskInfo:taskDetail:* <---> * 代表任意字符)
     * 
     * @param pattern
     * @return Set<Object>
     */
    public Set<Object> keys(Object pattern);

    /**
     * 根据 key 删除对应的 value
     * 
     * @param key
     */
    public boolean delete(Object key);

    /**
     * 根据 key 获取个数
     * 
     * @param key
     */
    public int count(Object key);

    /**
     * 批量删除对应的 value
     * 
     * @param keys
     */
    public void delete(String[] keys);

    /**
     * 批量删除 key(key 值可为模糊匹配 ---taskInfo:taskDetail:* <---> * 代表任意字符)
     * 
     * @param pattern
     */
    public long deletePattern(Object pattern);

    /**
     * 批量删除对应的 value
     * 
     * @param keys
     */
    public long delete(Set<Object> keys);

    /**
     * 写入缓存(操作字符串)
     * 
     * @param key
     * @param value
     * @return boolean
     */
    public boolean vSet(Object key, Object value);

    /**
     * 写入缓存设置时效时间(操作字符串)
     * 
     * @param key
     * @param value
     * @return boolean
     */
    public boolean vSet(Object key, Object value, Long expireTime);

    /**
     * 更新写入缓存设置时效时间(操作字符串)
     * 
     * @param key
     * @return boolean
     */
    public boolean vSetUpdate(Object key, Long expireTime);

    /**
     * 读取缓存(操作字符串)
     * 
     * @param key
     * @return Object
     */
    public Object vGet(Object key);

    /**
     * 哈希 添加(操作 hash)
     * 
     * @param key
     * @param hashKey
     * @param value
     */
    public void hmSet(Object key, Object hashKey, Object value);

    /**
     * 哈希 添加(操作 hash)
     * 
     * @param key
     * @param map
     */
    public void hmSetAll(Object key, Map<Object, Object> map);

    /**
     * 哈希获取数据(操作 hash)
     * 
     * @param key
     * @return Map<Object, Object>
     */
    public Map<Object, Object> hmGet(Object key);

    /**
     * 哈希获取数据(操作 hash)
     * 
     * @param key
     * @param hashKey
     * @return Object
     */
    public Object hmGet(Object key, Object hashKey);

    /**
     * 哈希删除数据(操作 hash)
     * 
     * @param key
     * @param hashKey
     * @return Object
     */
    public Object hmDel(Object key, Object hashKey);

}

抽象类 中我们进行了 RedisTemplate 的初始化以及序列化:

public abstract class AbstractBaseRedisDao<K, V> {@Resource(name = "redisTemplate")
    protected RedisTemplate<K, V> redisTemplate;

    /**
     * 设置 redisTemplate
     * 
     * @param redisTemplate
     */
    public void setRedisTemplate(RedisTemplate<K, V> redisTemplate) {this.redisTemplate = redisTemplate;}

    /**
     * 获取 RedisSerializer
     */
    protected RedisSerializer<String> getRedisSerializer() {return redisTemplate.getStringSerializer();
    }
}

在实现类中我们通过操作 RestTemplate 来实现接口中的方法~

Redis 缓存实战

首先,我们如果想在 Spring Boot 项目中启用缓存,需要在启动类上加上注解@EnableCaching,这个是重点,要记住了!

首先介绍一下注解三剑客:@Cacheable @CachePut@CacheEvict

  • @Cacheable:主要针对方法配置,能够根据方法的请求参数对其进行缓存,常用于查询操作
  • @CachePut:主要针对方法配置,能够根据方法的请求参数对其进行缓存,常用于修改操作
  • @CacheEvict:清空缓存,主要用于删除操作。

下面我们来看一下用法:


    /**
     *    value: 缓存的名称
     *    key: 缓存的键
     *    return 缓存的值
     */ 
    @Override
    @Cacheable(value = "users", key = "#id")
    public UserDO findOne(Long id) {
        // 如果我们第二次访问的时候,控制台没有打印出这句话说明是从缓存中取出
        log.info("From MYSQL");
        return userMapper.get(id);
    }

    @Override
    @CachePut(value = "users", key = "#userDO.id")
    public UserDO update(UserDO userDO) {
        // 执行之后,再次访问 findOne 的时候,应当没有打印出“From MySQL”,且返回的是我们修改后的值,说明这一步缓存成功
        if (userMapper.update(userDO) > 0) {return userMapper.get(userDO.getId());
        }
        return null;
    }

    @Override
    @CacheEvict(value = "users", key = "#id")
    public int delete(Long id) {
        // 执行之后去 rdm 中查看即可
        return userMapper.delete(id);
    }

测试 1

第一次访问 findOne

第二次访问 findOne:

仍然是刚刚的结果,但是控制台没有打印出任何东西,说明缓存成功


测试 2

调用 update 后再次调用 findOne:

可以看出信息已被修改且未访问数据库


测试 3

访问 delete,查看 rdm:

说明删除成功~

源码地址

Github
Gitee

记得顺手点个 star,您的肯定是对我写作最大的动力!

公众号

原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知

正文完
 0