springdata2 (4) redis技术整合

1,096 阅读3分钟

1. springboot整合Jedis

流程: 引入 spring-boot-starter-data-redisjedis 依赖:

  • 开发 classpath:jedis-pool.properties:配置jedis连接池,均以 spring.redis.jedis.pool 为前缀:
    • max-active=1024:连接池最大连接数,负值表示无限制。
    • max-idle=200:连接池中的最大空闲连接数。
    • min-idle=0:连接池中的最小空闲连接数。
    • max-wait=10000:连接池最大阻塞等待时间,单位毫秒,负值表示无限制。

源码:/springdata-redis/

  • xml:pom.xml
<!--jedis-->
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>2.9.0</version>
			<scope>compile</scope>
		</dependency>

		<!--spring-boot-starter-data-redis-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>
  • web:jedis-pool.properties
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.jedis.pool.max-active=1024
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.jedis.pool.max-wait=10000
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle=200
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle=0

1.1 整合单机redis

流程:

  • 在主配中配置单机jedis,均以 spring.redis 为前缀:
    • database=0:使用redis中的数据库索引,默认使用0号。
    • host=127.0.0.1:单机redis-server的主机地址,默认127.0.0.1,对外开放使用0.0.0.0。
    • port=6379:单机redis-server的端口,默认6379
    • timeout=3000:连接超时时间,单位毫秒。
    • password=1234:redis-server的认证密码,默认为空。
  • 开发 c.y.s.config.JedisConfig
    • 标记 @Configuration 使其成为配置类。
    • 使用 @PropertySource() 引入Jedis连接池属性文件。
    • 使用 @Value 将属性文件中的值注入类属性变量。
    • 配置 r.c.j.JedisPool 对应的bean。
  • tst: c.y.s.jedis.JedisConfigTest.jedisPool()
    • 注入 r.c.j.JedisPool,获取Jedis连接并操作数据。 源码:/springdata-redis/
  • web:application.properties
# redis相关
# 单机redis-server的主机地址,默认127.0.0.1
spring.redis.host=127.0.0.1
# 单机redis-server的端口号,默认6379
spring.redis.port=6379
# 连接超时时间为3秒
spring.redis.timeout=3000
# 认证密码,默认为空
# spring.redis.password=123
  • src:c.y.s.config.JedisConfig
package com.yap.springdata2redis.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * @author yap
 */
@Configuration
@PropertySource("classpath:jedis-pool.properties")
public class JedisConfig {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.password}")
    private String password;

    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;

    @Value("${spring.redis.jedis.pool.min-idle}")
    private int minIdle;

    @Value("${spring.redis.jedis.pool.max-active}")
    private int maxActive;

    @Value("${spring.redis.jedis.pool.max-wait}")
    private long maxWait;

    @Bean
    public JedisPool jedisPoolFactory() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMinIdle(minIdle);
        jedisPoolConfig.setMaxTotal(maxActive);
        jedisPoolConfig.setMaxWaitMillis(maxWait);
        jedisPoolConfig.setJmxEnabled(true);
        return new JedisPool(jedisPoolConfig, host, port, timeout, password);
    }
}

  • src:c.y.s.jedis.JedisConfigTest.jedisPool()
package com.yap.springdata2redis.jedis;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisSentinelPool;

/**
 * @author yap
 */
@SpringBootTest
class JedisConfigTest {

    @Autowired
    private JedisPool jedisPool;

    @Test
    void jedisPool() {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.setex("name", 5, "100");
            System.out.println(jedis.get("name"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

1.2 整合哨兵redis

流程:

  • 开发 classpath:jedis-sentinel.properties:均以 spring.redis 为前缀:
    • sentinel.nodes=127.0.0.1:27001,127.0.0.1:27002...:哨兵地址列表。
    • sentinel.master=my-master:哨兵监控的主从结构名。
    • timeout=3000:连接超时时间,单位毫秒。
  • 开发配置类 c.y.s.config.JedisSentinelConfig
    • 使用 @PropertySource() 引入哨兵属性文件及Jedis连接池属性文件。
    • 使用 @Value 将属性文件中的值注入对应属性变量。
    • 配置 r.c.j.JedisSentinelPool 对应的bean。
  • tst: c.y.s.jedis.JedisConfigTest.jedisSentinel()
    • 注入 r.c.j.JedisSentinelPool,获取Jedis连接并操作数据。 源码:/springdata-redis/
  • web:jedis-sentinel.properties
# redis-cluster相关
# 哨兵地址列表
spring.redis.sentinel.nodes=127.0.0.1:27007,127.0.0.1:27008,127.0.0.1:27009
# 哨兵监控的主从结构名
spring.redis.sentinel.master=my-master
# 连接超时时间为3秒
spring.redis.timeout=3000
  • src:c.y.s.config.JedisSentinelConfig
package com.yap.springdata2redis.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * @author yap
 */
@Configuration
@PropertySource({"classpath:jedis-pool.properties", "classpath:jedis-sentinel.properties"})
public class JedisSentinelConfig {

    @Value("${spring.redis.sentinel.nodes}")
    private String sentinelNodes;

    @Value("${spring.redis.sentinel.master}")
    private String master;

    @Value("${spring.redis.timeout}")
    private String timeout;

    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;

    @Value("${spring.redis.jedis.pool.min-idle}")
    private int minIdle;

    @Value("${spring.redis.jedis.pool.max-active}")
    private int maxActive;

    @Value("${spring.redis.jedis.pool.max-wait}")
    private long maxWait;

    @Bean
    public JedisSentinelPool jedisSentinelPool() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMinIdle(minIdle);
        jedisPoolConfig.setMaxTotal(maxActive);
        jedisPoolConfig.setMaxWaitMillis(maxWait);
        jedisPoolConfig.setJmxEnabled(true);

        String[] servers = sentinelNodes.split(",");
        Set<String> sentinels = new HashSet<>(Arrays.asList(servers));
        return new JedisSentinelPool(master, sentinels, jedisPoolConfig, timeout);
    }
}
  • src:c.y.s.jedis.JedisConfigTest.jedisSentinel()
package com.yap.springdata2redis.jedis;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisSentinelPool;

/**
 * @author yap
 */
@SpringBootTest
class JedisConfigTest {

    @Autowired
    private JedisSentinelPool jedisSentinelPool;

    @Test
    void jedisSentinelPool() {
        try (Jedis jedis = jedisSentinelPool.getResource()) {
            jedis.setex("name", 5, "100");
            System.out.println(jedis.get("name"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

1.3 整合集群redis

  • 开发 classpath:jedis-cluster.properties:均以 spring.redis 为前缀:
    • cluster.nodes=127.0.0.1:7011,127.0.0.1:7012...:集群地址列表。
    • timeout=3000:连接超时时间,单位毫秒。
  • 开发配置类 c.y.s.config.JedisClusterConfig
    • 使用 @PropertySource() 引入集群属性文件及Jedis连接池属性文件。
    • 使用 @Value 将属性文件中的值注入对应属性变量。
    • 配置 r.c.j.JedisCluster 对应的bean。
  • tst: c.y.s.jedis.JedisConfigTest.jedisCluster()
    • 注入 r.c.j.JedisCluster,直接操作集群数据。
      源码:/springdata-redis/
  • web:jedis-cluster.properties
# redis-cluster相关
# 集群redis-server的服务列表
spring.redis.cluster.nodes=127.0.0.1:7011,127.0.0.1:7012,127.0.0.1:7013,127.0.0.1:7014,127.0.0.1:7015,127.0.0.1:7016
# 连接超时时间为3秒
spring.redis.timeout=3000
  • src:c.y.s.config.JedisClusterConfig
package com.yap.springdata2redis.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;

import java.util.HashSet;
import java.util.Set;

/**
 * @author yap
 */
@Configuration
@PropertySource({"classpath:jedis-pool.properties", "classpath:jedis-cluster.properties"})
public class JedisClusterConfig {

    @Value("${spring.redis.cluster.nodes}")
    private String clusterNodes;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.jedis.pool.max-idle}")
    private int maxIdle;

    @Value("${spring.redis.jedis.pool.min-idle}")
    private int minIdle;

    @Value("${spring.redis.jedis.pool.max-active}")
    private int maxActive;

    @Value("${spring.redis.jedis.pool.max-wait}")
    private long maxWait;

    @Bean
    public JedisCluster jedisCluster() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMinIdle(minIdle);
        jedisPoolConfig.setMaxTotal(maxActive);
        jedisPoolConfig.setMaxWaitMillis(maxWait);
        jedisPoolConfig.setJmxEnabled(true);

        Set<HostAndPort> nodes = new HashSet<>();
        // [[0.0.0.0, 7011], 0.0.0.0:7012, 0.0.0.0:7013, 0.0.0.0:7014, 0.0.0.0:7015, 0.0.0.0:7016]
        String[] servers = clusterNodes.split(",");
        for (String server : servers) {
            String[] kv = server.split(":");
            nodes.add(new HostAndPort(kv[0].trim(), Integer.parseInt(kv[1])));
        }
        return new JedisCluster(nodes, timeout, jedisPoolConfig);
    }
}

  • src:c.y.s.jedis.JedisConfigTest.jedisCluster()
package com.yap.springdata2redis.jedis;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisSentinelPool;

/**
 * @author yap
 */
@SpringBootTest
class JedisConfigTest {

    @Autowired
    private JedisCluster jedisCluster;

    @Test
    void jedisCluster() {
        try {
            jedisCluster.setex("name", 5, "100");
            System.out.println(jedisCluster.get("name"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2. springboot整合StringRedisTemplate

概念: StringRedisTemplate 是Jedis的高度封装,相比Jedis而言,可以更方便地更换redis的java客户端,且多了自动管理连接池的特性,但是它的效率要低于Jedis:

  • 引入 spring-boot-starter-data-redis 依赖。
  • 在主配中配置redis:均以 spring.redis 为前缀:
    • database=0:使用redis中的数据库索引,默认使用0号。
    • host=127.0.0.1:单机redis-server的主机地址,默认127.0.0.1,对外开放使用0.0.0.0。
    • port=6379:单机redis-server的端口,默认6379
    • timeout=3000:连接超时时间,单位毫秒。
    • lettuce.pool.max-active=1024:连接池最大连接数,负值表示无限制。
    • lettuce.pool.max-idle=200:连接池中的最大空闲连接数,默认值是8,负值表示无限制。
    • lettuce.pool.min-idle=0:连接池中的最小空闲连接数,默认值是0,负值表示无限制。
    • lettuce.pool.max-wait=10000:连接池最大阻塞等待时间,单位毫秒,负值表示永不超时。
  • tst: c.y.s.template.StringRedisTemplateTest
    • 注入 o.s.d.r.c.StringRedisTemplate,直接操作集群数据。
    • stringRedisTemplate.opsForValue() 对象用于操作字符串。
    • stringRedisTemplate.opsForHash() 对象用于操作hash。
    • stringRedisTemplate.opsForList() 对象用于操作list。
    • stringRedisTemplate.opsForSet() 对象用于操作set。
    • stringRedisTemplate.opsForZSet() 对象用于操作sorted set。 源码:/springdata-redis/
  • xml:pom.xml
		<!--spring-boot-starter-data-redis-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>
  • web:application.properties
# redis相关
# 单机redis-server的主机地址,默认127.0.0.1
spring.redis.host=127.0.0.1
# 单机redis-server的端口号,默认6379
spring.redis.port=6379
# 连接超时时间为3秒
spring.redis.timeout=3000
# 认证密码,默认为空
# spring.redis.password=123

# 连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-active=1024
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.lettuce.pool.max-wait=10000
# 连接池中的最大空闲连接
spring.redis.lettuce.pool.max-idle=200
# 连接池中的最小空闲连接
spring.redis.lettuce.pool.min-idle=0
  • src:c.y.s.template.StringRedisTemplateTest
package com.yap.springdata2redis.template;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.concurrent.TimeUnit;

/**
 * @author yap
 */
@SpringBootTest
class StringRedisTemplateTest {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Test
    void opsForValue() {
        // 存储a=1,60秒后过期
        stringRedisTemplate.opsForValue().set("a", "1", 60, TimeUnit.SECONDS);

        // 对a的值自增
        stringRedisTemplate.boundValueOps("a").increment(1);

        // 获取a
        System.out.println(stringRedisTemplate.opsForValue().get("a"));

        // 获取a的过期时间
        System.out.println(stringRedisTemplate.getExpire("a"));

        // 删除a
        stringRedisTemplate.delete("a");

        // 返回是否存在a
        System.out.println(stringRedisTemplate.hasKey("a"));
    }

    @Test
    void opsForSet() {

        // 向ages中存放set集合
        stringRedisTemplate.opsForSet().add("ages", "1", "2", "3");

        // 设置ages过期时间
        stringRedisTemplate.expire("ages", 5000, TimeUnit.MILLISECONDS);

        // 根据ages查看集合中是否存在指定数据
        System.out.println(stringRedisTemplate.opsForSet().isMember("ages", "1"));

        // 获取ageSet集合中的所有元素
        System.out.println(stringRedisTemplate.opsForSet().members("ages"));
    }
}