java连接腾讯云上的redis

腾讯云上的配置

在安全组上打开相关的端口即可

1569516112638

"来源" 就是你的目标服务器的ip(也可以是0.0.0.0/0) 协议端口可以用范围的写法 TCP:6379-6389

然后需将redis运行使用的配置文件redis.conf默认bind 127.0.0.1(只允许本地访问)注释掉(或者改为0.0.0.0)

# bind 127.0.0.1
protected-mode no 从yes改为no

redis连接单机和集群

依赖 pom.xml

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

<!-- redis依赖commons-pool 这个依赖一定要添加 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.2</version>
</dependency>

redis参数的配置文件

redis.properties

#启动集群
#redis.cluster=true

########################### reids单机配置 ##############################
#Matser的ip地址
redis.host=49.235.196.22
#端口号
redis.port=6380
#如果有密码
#redis.password=
#客户端超时时间单位是毫秒 默认是2000
redis.timeout=5000


########################### jedis单机与集群的公共配置 ##############################
#最大空闲数
redis.maxIdle=300
#连接池的最大数据库连接数。设为0表示无限制,如果是jedis 2.4以后用redis.maxTotal
#redis.maxActive=600
#控制一个pool可分配多少个jedis实例,用来替换上面的redis.maxActive,如果是jedis 2.4以后用该属性
redis.maxTotal=1000
#最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
redis.maxWaitMillis=1000
#连接的最小空闲时间 默认1800000毫秒(30分钟)
redis.minEvictableIdleTimeMillis=300000
#每次释放连接的最大数目,默认3
redis.numTestsPerEvictionRun=1024
#逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
redis.timeBetweenEvictionRunsMillis=30000
#是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
redis.testOnBorrow=true
#在空闲时检查有效性, 默认false
redis.testWhileIdle=true

########################### redis集群配置 ##############################
redis.clusterNodes=49.235.196.22:7001,49.235.196.22:7002,49.235.196.22:7003,49.235.196.22:7004,49.235.196.22:7005,49.235.196.22:7006
redis.maxRedirects=3

#哨兵模式
#redis.sentinel.host1=192.168.177.128
#redis.sentinel.port1=26379

#redis.sentinel.host2=172.20.1.231
#redis.sentinel.port2=26379

application.yml

redis:
  cluster:
    true

三个Redis的配置类,RedisConfig:集群和单机的公共部分,SinglenRedisConfig单机特有的配置,ClusterRedisConfig集群特有的配置

package per.qiao.config;


import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

import java.util.List;

/**
 * Create by IntelliJ Idea 2018.2
 *
 * @author: qyp
 * Date: 2019-09-29 17:15
 */
@Getter
@Setter
public abstract class RedisConfig {

    /**
     * 最大空闲数
     */
    public Integer maxIdle;

    /**
     * 控制一个pool可分配多少个jedis实例
     */
    public Integer maxTotal;

    /**
     * 最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
     */
    public Integer maxWaitMillis;

    /**
     * 连接的最小空闲时间 默认1800000毫秒(30分钟)
     */
    public Integer minEvictableIdleTimeMillis;

    /**
     * 每次释放连接的最大数目,默认3
     */
    public Integer numTestsPerEvictionRun;

    /**
     * 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
     */
    public long timeBetweenEvictionRunsMillis;

    /**
     * 是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
     */
    public boolean testOnBorrow;

    /**
     * 在空闲时检查有效性, 默认false
     */
    public boolean testWhileIdle;


    /**
     * JedisPoolConfig 连接池
     *
     * @return
     */
    @Bean
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        // 最大空闲数
        jedisPoolConfig.setMaxIdle(maxIdle);
        // 连接池的最大数据库连接数
        jedisPoolConfig.setMaxTotal(maxTotal);
        // 最大建立连接等待时间
        jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
        // 逐出连接的最小空闲时间 默认1800000毫秒(30分钟)
        jedisPoolConfig.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        // 每次逐出检查时 逐出的最大数目 如果为负数就是 : 1/abs(n), 默认3
        jedisPoolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
        // 逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
        jedisPoolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        // 是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
        jedisPoolConfig.setTestOnBorrow(testOnBorrow);
        // 在空闲时检查有效性, 默认false
        jedisPoolConfig.setTestWhileIdle(testWhileIdle);
        return jedisPoolConfig;
    }

    /**
     * 单机构建JedisConnectionFactory对象
     * @param jedisPoolConfig
     * @return
     */
    public JedisConnectionFactory redisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
        return null;
    }

    /**
     * 集群redis构建JedisConnectionFactory对象
     * @param jedisPoolConfig
     * @param redisClusterConfiguration
     * @return
     */
    public JedisConnectionFactory redisConnectionFactory(JedisPoolConfig jedisPoolConfig, RedisClusterConfiguration redisClusterConfiguration) {

        return null;
    }

    /**
     * 实例化 RedisTemplate 对象
     *
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        initDomainRedisTemplate(redisTemplate, redisConnectionFactory);
        return redisTemplate;
    }

    /**
     * 设置数据存入 redis 的序列化方式,并开启事务
     *
     * @param redisTemplate
     * @param factory
     */
    public void initDomainRedisTemplate(RedisTemplate<String, Object> redisTemplate, RedisConnectionFactory factory) {
        //如果不配置Serializer,那么存储的时候缺省使用String,如果用User类型存储,那么会提示错误User can't cast to String!
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        // 开启事务
        //redisTemplate.setEnableTransactionSupport(true);
        redisTemplate.setConnectionFactory(factory);
    }
}

SinglenRedisConfig.java

package per.qiao.config;

import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import redis.clients.jedis.JedisPoolConfig;

/**
 * PropertySource加载文件到当前类上下文的 Environment 中
 */
@Configuration
@PropertySource("classpath:redis.properties")
@ConfigurationProperties(prefix = "redis")
@ConditionalOnMissingBean(ClusterRedisConfig.class)
@Getter
@Setter
public class SinglenRedisConfig extends RedisConfig {

    /**
     * host,port,timeout
     * 这三个是单机属性
     */
    private String host;

    private Integer port;

    private Integer timeout;

    /**
     * 单机版配置
     *
     * @param @param  jedisPoolConfig
     * @param @return
     * @return JedisConnectionFactory
     * @throws
     * @Title: JedisConnectionFactory
     * @autor lpl
     * @date 2018年2月24日
     */
    @Bean
    public JedisConnectionFactory redisConnectionFactory(JedisPoolConfig jedisPoolConfig) {
        JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
        //连接池  
        redisConnectionFactory.setPoolConfig(jedisPoolConfig);
        //IP地址  
        redisConnectionFactory.setHostName(host);
        //端口号  
        redisConnectionFactory.setPort(port);
        //如果Redis设置有密码  
        //JedisConnectionFactory.setPassword(password);

        //客户端超时时间单位是毫秒  
        redisConnectionFactory.setTimeout(timeout);
        return redisConnectionFactory;
    }
}

ClusterRedisConfig.java

package per.qiao.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.stereotype.Component;
import redis.clients.jedis.JedisPoolConfig;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author qiao
 */
@Configuration
@PropertySource("classpath:redis.properties")
//@EnableConfigurationProperties(ClusterRedisConfig.class)
@ConfigurationProperties(prefix = "redis")
//@ConditionalOnExpression("#{'true'.equals(environment['redis.cluster'])}")
//@ConditionalOnExpression("'${redis.cluster}'=='true'")
@ConditionalOnExpression("${redis.cluster}")
@Getter
@Setter
public class ClusterRedisConfig extends RedisConfig {

    /**
     * clusterNodes,mmaxRedirectsac
     * 这两个是集群属性
     */
    private List<String> clusterNodes;

    private Integer maxRedirects;

    /**
     * Redis集群的配置
     *
     * @return RedisClusterConfiguration
     * @throws
     * @autor lpl
     * @date 2017年12月22日
     */
    @Bean
    public RedisClusterConfiguration redisClusterConfiguration() {
        RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration();

        Set<RedisNode> nodes = clusterNodes.stream().map(ipPort -> {
            String[] ipAndPort = ipPort.split(":");
            return new RedisNode(ipAndPort[0].trim(), Integer.valueOf(ipAndPort[1]));
        }).collect(Collectors.toSet());

        redisClusterConfiguration.setClusterNodes(nodes);
        redisClusterConfiguration.setMaxRedirects(maxRedirects);

        return redisClusterConfiguration;
    }

    /**
     * 配置工厂
     *
     * @param @param  jedisPoolConfig
     * @param @return
     * @return JedisConnectionFactory
     * @throws
     * @Title: JedisConnectionFactory
     * @autor lpl
     * @date 2017年12月22日
     */
    @Bean
    public JedisConnectionFactory redisConnectionFactory(JedisPoolConfig jedisPoolConfig, RedisClusterConfiguration redisClusterConfiguration) {
        JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory(redisClusterConfiguration, jedisPoolConfig);

        return redisConnectionFactory;
    }

}

测试

@SpringBootTest
@RunWith(SpringRunner.class)
public class RedisTest {

    @Autowired
    RedisUtil redisUtil;

    @Test
    public void test() {
        //redisUtil.del("abc");
        redisUtil.set("abc", "1234567");
        System.out.println("================");
        Object myKey = redisUtil.get("abc");
        System.out.println(myKey);
    }
}

遗留问题

问题1:在集群配置上出了个问题ClusterRedisConfig

问题一、使用@PropertySource("classpath:redis.properties")加载配置文件,然后使用@ConditionalOnExpression获取不到配置文件中的值

使用@PropertySource("classpath:redis.properties")加载指定的属性文件,然后使用@ConfigurationProperties(prefix = "redis")指定前缀,最后使用@ConditionalOnExpression("${redis.cluster}")判断是否加载当前类

但是这个判断不能按照设想进行控制。

1. 当我将属性redis.cluster放到redis.properties中时,获取不到值,抛there is still more data in the expression in 'lcurly({)'错误
2. 当我把属性redis.cluster放到application.yml文件中时,是可以成功的。

猜想:yml文件最先加载,@ConditionalOnExpression又比@PropertySource先加载,所以拿不到数据

问题2:在使用lettuce连接redis时,项目总是报集群的连接超时,但是项目可以正常使用

这是使用lettuce(生菜)连接的yml配置文件

spring:
 redis:
     database: 1
 #   host:
 #   port:
 #   password:
     cluster:
       nodes:
        - 49.235.196.22:7001
        - 49.235.196.22:7002
        - 49.235.196.22:7003
        - 49.235.196.22:7004
        - 49.235.196.22:7005
        - 49.235.196.22:7006
     lettuce:
      pool:
         # 连接池最大连接数 默认8 ,负数表示没有限制
        max-active: 8
         # 连接池中的最大空闲连接 默认8
        max-idle: 8
         # 连接池中的最小空闲连接 默认0
        min-idle: 0
         # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认-1
        max-wait: -1s
     host: 49.235.196.22
     port: 7001
    #timeout: 30000s

这是配置类

@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig2 {

    /**
     * springboot2.x 使用LettuceConnectionFactory 代替 RedisConnectionFactory
     * application.yml配置基本信息后,springboot2.x  RedisAutoConfiguration能够自动装配
     * LettuceConnectionFactory 和 RedisConnectionFactory 及其 RedisTemplate
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory){
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }
}

参考

原文地址:https://www.cnblogs.com/qiaozhuangshi/p/11611237.html