1. SpringBoot集成Redis

在使用客户端连接 Redis 时,例如 Jedis

// 创建连接池
JedisPool pool = new JedisPool("localhost", 6379,"default","123456");
// 获取客户端
try (Jedis jedis = pool.getResource()) {
    // 存入一个字符串
    jedis.set("foo", "bar");
}

直接集成客户端,需要我们自己维护连接配置,获取客户端连接,再执行操作,最后还需要释放资源。Spring 提供了 Spring Data RedisSpring Boot Data Redis Starter ,在 Spring Boot 环境中,可以很方便的连接并操作 Redis

2. Spring Data Redis

Spring Data Redis 用于简化 Redis 的配置和操作,提供了与存储进行交互的低级和高级抽象,从而使用户无需担心基础设施问题。

核心特性:

  • 连接:支持多个 Redis 客户端包(如 LettuceJedis ),提供低级抽象,简化了连接管理。
  • 异常转换:将 Redis 客户端异常转换为 Spring 的数据访问异常层次结构,便于异常处理。
  • RedisTemplate:提供了一个高级抽象,用于执行各种 Redis 操作,包括异常转换和序列化支持,简化了 Redis 操作。
  • 发布/订阅支持:如为消息驱动的 POJO 提供的 MessageListenerContainer ,支持发布/订阅模式。
  • Redis SentinelRedis Cluster 支持:提供对 Redis 的高可用性和集群配置的支持。
  • 响应式API:默认使用 Lettuce 提供响应式编程能力,支持非阻塞的异步操作。
  • 序列化器:包括JDKStringJSONSpring Object/XML映射序列化器,方便数据序列化和反序列化。
  • JDK集合实现:在Redis之上实现JDK集合,允许以分布式方式使用集合数据结构。
  • 原子计数器支持类:提供原子计数器类,支持分布式环境下的计数器操作。
  • 排序和管道功能:支持排序和管道化功能,提高数据处理效率。
  • SORTSORT/GET模式及返回批量值的专门支持:提供对Redis排序命令及其变体的深入支持。
  • Spring 3.1缓存抽象实现(Spring Cache):为Spring 3.1的缓存抽象提供 Redis 实现,支持缓存数据的存储和检索。
  • 仓库接口自动实现:包括使用 @EnableRedisRepositories 注解支持自定义查询方法的仓库接口自动实现,简化了数据访问层的开发。
  • CDI 支持:提供对依赖注入(CDI)的支持,便于在 Spring 应用中使用 CDI 方式管理仓库。

3. Spring Boot Data Redis Starter

Spring Data Redis 的基础上,提供了 Spring Boot 启动器:

  • spring-boot-starter-data-redis:适用传统应用程序
  • spring-boot-starter-data-redis-reactive:适用响应式应用程序

3.1 起步依赖

Spring Boot 中集成 Redis ,只需要引入以下依赖即可:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

spring-boot-starter-data-redis 中包含了 Lettuce 客户端和 Spring Data Redis,无需再引入其他依赖:

image-20240920164532067

3.2 自动配置

spring-boot-autoconfigure 包中,提供了 Redis 自动配置功能:

image-20240920164544735

核心类介绍:

  • ClientResourcesBuilderCustomizer:客户端资源定制器,允许开发者对 Redis 连接进行细粒度的控制和优化。
  • JedisClientConfigurationBuilderCustomizerJedis 配置定制器,用于添加自定义的 Jedis 客户端配置。
  • LettuceClientConfigurationBuilderCustomizerLettuce 配置定制器,用于添加自定义的 Lettuce 客户端配置。
  • JedisConnectionConfigurationJedis 连接自动配置类
  • LettuceConnectionConfigurationLettuce 连接自动配置类
  • RedisAutoConfigurationRedis 自动配置类,主动注册 RedisTemplateStringRedisTemplate
  • RedisPropertiesRedis属性配置类,加载 application.yml 中的配置到应用环境中
  • RedisConnectionDetails:获取 Redis 连接信息
  • RedisReactiveAutoConfigurationReactive Redis 环境下的自动配置类,主动注册ReactiveRedisTemplateReactiveStringRedisTemplate
  • RedisRepositoriesAutoConfigurationRedis Repository 自动配置类,可以通过定义 Repository 接口操作 Redis
  • RedisUrlSyntaxFailureAnalyzerURL 语法错误分析器

4. 配置

RedisProperties 提供了 RedisSpring Boot 环境中的所有配置项,配置前缀为spring.data.redis

4.1 客户端类型

客户端类型对应的配置项为 spring.data.redis.client-type ,可配置项对应的类为RedisProperties.ClientType

public static enum ClientType {
   LETTUCE,
   JEDIS;
}

默认为 LETTUCE ,并且 Spring Boot 起步依赖中也包含了该包,如果想要使用 JEDIS ,可以如下配置:

spring:
  data:
    redis:
      client-type: jedis
      # 设置连接到 Redis 时使用的客户端名称(自定义),可用于日志记录和监控目的
      client-name: spring-boot-redis

此外还需要额外引入 Jedis 客户端包:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>5.1.2</version>
</dependency>

4.2 连接池

连接池(Connection Pool)需要在具体的客户端下进行配置,例如 jedis 连接池:

spring:
  data:
    redis:
      client-type: jedis
      jedis:
        pool:
          enabled: true
          max-active: 8
          max-idle: 8
          max-wait: 10000
          min-idle: 0
          time-between-eviction-runs: 10000

例如 lettuce 连接池:

spring:
  data:
    redis:
      client-type: lettuce
      lettuce:
        pool:
          enabled: true
          max-active: 8
          max-idle: 8
          max-wait: 10000
          min-idle: 0
          time-between-eviction-runs: 10000

关于连接池的配置项说明如下:

  • enabled:是否启用连接池,设置为 true (默认)表示开启,推荐使用连接池。
  • max-active:连接池中最大活跃连接数,默认 8 。可以限制客户端同时占用的资源数量,避免过多的连接占用Redis 服务器资源或客户端资源。
  • max-idle:连接池中最大空闲连接数,默认 8
  • min-idle:连接池中最小空闲连接数,默认 0 (不会强制保持任何空闲连接)。
  • max-wait:当连接池中没有可用连接时,获取连接的最大等待时间(以毫秒为单位),默认 -1 (一直等待)。如果没有可用的连接,则尝试获取连接的操作将抛出异常。
  • timeBetweenEvictionRuns:空闲连接检测器两次运行之间的间隔时间(以毫秒为单位)。设置为 10 秒时,连接池将每 10 秒检查一次空闲连接,并根据需要关闭那些超过最大空闲时间限制的连接。以保持连接池的健康状态,避免因为长时间未使用的连接而占用资源。

4.3 连接配置

Spring Boot 默认支持三种部署方式的连接,都配置了的情况下,加载优先级为:集群 > 哨兵 > 单机。

4.3.1 单机

单机模式用于开发、测试,不具备高可用性,可以使用 spring.data.redis.url 直接配置所有的连接信息,规则如下:

redis://:{认证密码}@{Ip}:{端口}/{数据库序列号}

示例:

spring:
  data:
    redis:
      url: redis://:123456@127.0.0.1:6379/0

也可以分别配置:

spring:  
  data:  
    redis:  
      # Ip
      host: 127.0.0.1  
      # 端口
      port: 6379  
      # 数据库序列号
      database: 0 
      # 认证用户名
      username: default
      # 认证密码
      password: 123456  

4.3.2 哨兵

哨兵模式相关的配置前缀为 spring.data.redis.sentinel ,示例:

spring:
  data:
    redis:
      client-type: lettuce
      database: 0
      # 哨兵模式
      sentinel:
        master: mymaster
        nodes: 192.168.56.104:26379,192.168.56.105:26379,192.168.56.106:26379
        # username: sentinel
        password: sentinel123456
      lettuce:
        pool:
          enabled: true
          max-active: 8
          max-idle: 8
          max-wait: 10000
          min-idle: 0
          time-between-eviction-runs: 10000

关于哨兵的配置项说明如下:

  • master:主节点名称。
  • nodesSentinel 节点的地址列表,多个以逗号分割,哨兵会获取到真实的主从节点地址并连接。
  • usernameRedis Sentinel 认证用户名。
  • passwordRedis Sentinel 认证用密码。

4.3.3 集群

集群模式相关的配置前缀为 spring.data.redis.cluster ,示例:

spring:
  data:
    redis:
      client-type: lettuce
      # 集群模式
      # 认证用户名
      # username: cluster
      # 认证密码
      password: cluster123456
      cluster:
        max-redirects: 5
        nodes:
          - 192.168.56.101:6379
          - 192.168.56.101:6380
          - 192.168.56.101:6381
          - 192.168.56.101:6382
          - 192.168.56.101:6383
          - 192.168.56.101:6390
      lettuce:
        pool:
          enabled: true
          max-active: 8
          max-idle: 8
          max-wait: 10000
          min-idle: 0
          time-between-eviction-runs: 10000
        shutdown-timeout: 10000
      connect-timeout: 10000
      timeout: 10000

关于哨兵的配置项说明如下:

  • max-redirects: 集群连接时的最大重定向次数。当应用程序需要连接到集群中的某个节点时,如果该节点不可用或者出现了故障,可以尝试重新路由请求到其他节点,重定向次数设置了最大尝试次数。
  • nodes: 指定了集群中各个节点的地址和端口。

4.4 连接/读取超时

可以配置 Redis 连接、读取超时时间,示例:

spring:  
  data:  
    redis:  
      connect-timeout: 10000 
      timeout: 10000

关于超时配置项说明如下:

  • connect-timeout:指定客户端尝试连接到 Redis 服务器时的超时时间(毫秒为单位)。在指定时间内没有成功建立到 Redis 服务器的连接,将抛出异常。
  • timeout:指定 Redis 读取超时时间(毫秒为单位)。

4.5 SSL Bundle

支持基于 Spring Boot SSL Bundle 机制,配置 SSL 证书。

示例:

spring:
  data:
    redis:
      url: redis://:123456@127.0.0.1:6379/0
      ssl:
        # 是否开启 SSL
        enabled: true
        # Bundle 名称
        bundle: secure-service
  ssl:
    bundle:
      jks:
        secure-service:
          key:
            alias: "server"
          keystore:
            location: "classpath:server.p12"
            password: "secret"
            type: "PKCS12"

4.6 Redis Repository

可以开启通过定义 Repository 接口操作 Redis

spring:
  data:
    redis:
      repositories:
        enabled: true

4.7 Lettuce 独有

相比于 JedisLettuce 还提供了一些独有的配置:

spring:
  data:
    redis:
      lettuce:
        pool:
          enabled: true
        cluster:
          refresh:
            adaptive: true
            dynamic-refresh-sources: true
            period: 10000
        shutdown-timeout: 10000  

Lettuce 独有的配置项主要是集群自动刷新,例如,集群某个节点迁移了哈希槽,需要刷新本地的集群信息,说明如下:

  • shutdown-timeout: 连接池在关闭时的超时时间,单位是毫秒
  • cluster.refresh.adaptive:启用自适应集群拓扑刷新。 Lettuce 会动态地根据 Redis 集群的拓扑情况来更新本地的集群信息,以确保客户端能够正确地与集群通信。
  • cluster.refresh.dynamic-refresh-sources:启用动态刷新源。 Lettuce 在需要时从多个源刷新集群的拓扑信息,确保及时获取最新的集群状态。
  • cluster.refresh.period:了集群拓扑刷新的周期,单位是毫秒。

5. 入门案例

5.1 引入依赖

创建一个 Spring Boot 项目,引入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

5.2 配置连接

支持单机、复制、哨兵、集群模式,这里添加一个最简单的单机连接:

spring:
  data:
    redis:
      client-type: lettuce
      # URL
      # url: redis://:123456@127.0.0.1:6379/0
      # # Ip
       host: 127.0.0.1
      # # 端口
       port: 6379
      # # 数据库序列号
       database: 0
      # # 认证用户名
       username: default
      # # 认证密码
       password: 123456
      lettuce:
        pool:
          enabled: true
          max-active: 8
          max-idle: 8
          max-wait: 10000
          min-idle: 0
          time-between-eviction-runs: 10000
        shutdown-timeout: 10000
      connect-timeout: 10000
      timeout: 10000

5.3 操作模板类

RedisTemplate 是在 Spring Boot 环境中和 Redis 打交道的一个模板类,简化了与 Redis数据库的交互过程,我们可以更加便捷地进行 Redis 的各种操作,如数据存取、异常处理及序列化等。

StringRedisTemplateRedisTemplate 的一个扩展,由于大多数针对 Redis的操作都是基于字符串的,所以提供了一个专用的类来处理这些操作。

Spring Boot自动配置中,已经帮我们注册了这个两个对象:

@AutoConfiguration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean(RedisConnectionDetails.class)
    PropertiesRedisConnectionDetails redisConnectionDetails(RedisProperties properties) {
        return new PropertiesRedisConnectionDetails(properties);
    }

    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        return new StringRedisTemplate(redisConnectionFactory);
    }
}

RedisTemplate 提供了丰富的 API ,可以很方便的进行各种数据类型进行操作,同时也支持事务、管道、脚本、发布订阅等。

image-20240920165029086

示例,创建一个需要存储的用户对象, RedisTemplate 默认使用 JDK 序列化,所以需要实现 Serializable

public class User implements Serializable {

    private String name;

    private Integer age;

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}   

使用 RedisTemplate 进行操作:

@SpringBootTest
public class RedisTest {

    @Autowired
    RedisTemplate<Object, Object> redisTemplate;

    @Test
    public void test() {
        // 增
        User user = new User("张三", 18);
        redisTemplate.boundHashOps("session").put("id:8989", user);

        // 查
        User getUser = (User)redisTemplate.boundHashOps("session").get("id:8989");
        System.out.println(getUser);
    }
}

查看数据:

image-20240920165102780