redis 集群 分片 扩容_Springboot1.5.9集成Redis(单实例与分片集群)

前言

springboot集成redis只需要看懂RedisAutoConfiguration类即可!

pom依赖

<parent>    <groupId>org.springframework.bootgroupId>    <artifactId>spring-boot-starter-parentartifactId>    <version>1.5.9.RELEASEversion>parent><dependency>    <groupId>org.springframework.bootgroupId>    <artifactId>spring-boot-starter-data-redisartifactId>dependency>

下面简单解析下RedisAutoConfiguration类源码:

从类上面的注解可以看出spring自动装配redis是基于Jedis客户端实现.

@EnableConfigurationProperties(RedisProperties.class)指明了自动装配需要的配置,其中包含了单实例、哨兵模式、分片模式的配置,可以按需灵活使用.

@Configuration// 自动装配依赖条件@ConditionalOnClass({ JedisConnection.class, RedisOperations.class, Jedis.class }//启用RedisProperties配置类,注意该注解的目的是将使用@Configuration注解的类交给spring容器管理@EnableConfigurationProperties(RedisProperties.class)public class RedisAutoConfiguration {
/***  redis连接配置* Redis connection configuration.*/@Configuration@ConditionalOnClass(GenericObjectPool.class)protected static class RedisConnectionConfiguration {  // 基础配置  private final RedisProperties properties;  // 哨兵配置  private final RedisSentinelConfiguration sentinelConfiguration;  // 分片配置  private final RedisClusterConfiguration clusterConfiguration;  // 构造注入配置文件  public RedisConnectionConfiguration(RedisProperties properties,        ObjectProvider sentinelConfiguration,        ObjectProvider clusterConfiguration) {     this.properties = properties;     this.sentinelConfiguration = sentinelConfiguration.getIfAvailable();     this.clusterConfiguration = clusterConfiguration.getIfAvailable();  }  // 如果没有RedisConnectionFactory的实例则初始化一个redis工厂实例  @Bean  @ConditionalOnMissingBean(RedisConnectionFactory.class)  public JedisConnectionFactory redisConnectionFactory() throws UnknownHostException {     return applyProperties(createJedisConnectionFactory());  }  // 配置连接工厂的连接属性  protected final JedisConnectionFactory applyProperties(JedisConnectionFactory factory) {     configureConnection(factory);     if (this.properties.isSsl()) {        factory.setUseSsl(true);     }     factory.setDatabase(this.properties.getDatabase());     if (this.properties.getTimeout() > 0) {        factory.setTimeout(this.properties.getTimeout());     }     return factory;  }
 private void configureConnection(JedisConnectionFactory factory) {   if (StringUtils.hasText(this.properties.getUrl())) {      configureConnectionFromUrl(factory);   } else {      factory.setHostName(this.properties.getHost());      factory.setPort(this.properties.getPort());      if (this.properties.getPassword() != null) {         factory.setPassword(this.properties.getPassword());      }   }}      
 private void configureConnectionFromUrl(JedisConnectionFactory factory) {    String url = this.properties.getUrl();    if (url.startsWith("rediss://")) {       factory.setUseSsl(true);    }    try {       URI uri = new URI(url);       factory.setHostName(uri.getHost());       factory.setPort(uri.getPort());       if (uri.getUserInfo() != null) {          String password = uri.getUserInfo();          int index = password.lastIndexOf(":");          if (index >= 0) {             password = password.substring(index + 1);          }          factory.setPassword(password);       }    }catch (URISyntaxException ex) {       throw new IllegalArgumentException("Malformed 'spring.redis.url' " + url,ex);   }}
protected final RedisSentinelConfiguration getSentinelConfig() {    if (this.sentinelConfiguration != null) {        return this.sentinelConfiguration;     }    Sentinel sentinelProperties = this.properties.getSentinel();    if (sentinelProperties != null) {       RedisSentinelConfiguration config = new RedisSentinelConfiguration();       config.master(sentinelProperties.getMaster());       config.setSentinels(createSentinels(sentinelProperties));       return config;    }    return null; }/** * Create a {@link RedisClusterConfiguration} if necessary. * @return {@literal null} if no cluster settings are set. */ protected final RedisClusterConfiguration getClusterConfiguration() {    if (this.clusterConfiguration != null) {       return this.clusterConfiguration;    }    if (this.properties.getCluster() == null) {       return null;     }    Cluster clusterProperties = this.properties.getCluster();    RedisClusterConfiguration config = new RedisClusterConfiguration(          clusterProperties.getNodes());    if (clusterProperties.getMaxRedirects() != null) {       config.setMaxRedirects(clusterProperties.getMaxRedirects());    }    return config; }
// 哨兵节点配置private List createSentinels(Sentinel sentinel) {    List nodes = new ArrayList();    for (String node : StringUtils.commaDelimitedListToStringArray(sentinel.getNodes())) {      try {         String[] parts = StringUtils.split(node, ":");         Assert.state(parts.length == 2, "Must be defined as 'host:port'");         nodes.add(new RedisNode(parts[0], Integer.valueOf(parts[1])));      }catch (RuntimeException ex) {         throw new IllegalStateException("Invalid redis sentinel " + "property '" + node + "'", ex);      }   }   return nodes;}
// 创建连接工厂private JedisConnectionFactory createJedisConnectionFactory() {   JedisPoolConfig poolConfig = this.properties.getPool() != null? jedisPoolConfig() : new JedisPoolConfig();    // 如果配置了哨兵,则优先启用哨兵   if (getSentinelConfig() != null) {      return new JedisConnectionFactory(getSentinelConfig(), poolConfig);   }   // 配置分片则启用分片   if (getClusterConfiguration() != null) {      return new JedisConnectionFactory(getClusterConfiguration(), poolConfig);   }   // 没有配置集群则启用单实例   return new JedisConnectionFactory(poolConfig);}private JedisPoolConfig jedisPoolConfig() {   JedisPoolConfig config = new JedisPoolConfig();   RedisProperties.Pool props = this.properties.getPool();   config.setMaxTotal(props.getMaxActive());   config.setMaxIdle(props.getMaxIdle());   config.setMinIdle(props.getMinIdle());   config.setMaxWaitMillis(props.getMaxWait());   return config;}}/*** Standard Redis configuration.*/@Configurationprotected static class RedisConfiguration {  // 如果容器中没有redisTemplate则创建一个该实例对象  // 我们在使用的时候需要进行增强,所以只用我们直接生成一个redisTemplate的bean,此处则不会生效  @Bean  @ConditionalOnMissingBean(name = "redisTemplate")  public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)throws UnknownHostException {     RedisTemplate<Object, Object> template = new RedisTemplate<Object, Object>();     template.setConnectionFactory(redisConnectionFactory);     return template;  }  // 如果容器中没有StringRedisTemplate则创建一个该实例对象  @Bean  @ConditionalOnMissingBean(StringRedisTemplate.class)  public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)throws UnknownHostException {     StringRedisTemplate template = new StringRedisTemplate();     template.setConnectionFactory(redisConnectionFactory);     return template;  }}}

这个类非常容易看懂,所以实际上集成redis就变得非常简单了,下面来看看具体项目使用配置:

先看下yml配置文件,配置非常清晰,使用哪种模式按指定配置即可

spring:  redis:    #host: 127.0.0.1  #单实例在此配置ip,配置单实例必须屏蔽cluster max-redirects 与 nodes      #port: 6379  #单实例在此配置端口         password:    timeout: 20000    pool:      max-active: 8 #连接池最大连接数(使用负值表示没有限制)      min-idle: 0  #最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接        max-idle: 8 #最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放        max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)    sentinel:  #哨兵模式 适用于读多写少      master:  #配置主节点      nodes:   #配置从节点    cluster:   #集群在此配置节点,配置集群必须屏蔽host与port配置      max-redirects: 6 #最大的要重定向的次数(由于集群中数据存储在多个节点所以,在访问数据时需要通过节点进行转发)      nodes: 192.168.210.68:6379,192.168.210.68:6380,192.168.210.68:6381,... #分片至少要6个节点才能使用

再来看下在代码中使用

只用注入org.springframework.data.redis.core.RedisTemplate即可通过redisTemplate操作redis

另外由于redisTempate会将数据序列化后存储,而序列化默认使用JdkSerializationRedisSerializer,下面简单介绍下spring-data-redis的几个序列化类:

FastJson2JsonRedisSerializer: #序列化object对象为json字符串,存储的value值是带有双引号的,不利于反序列化GenericToStringSerializer: #将任何对象toString()后再序列化JacksonJsonRedisSerializer: #序列化object对象为json字符串,具备易读性Jackson2JsonRedisSerializer: #同JacksonJsonRedisSerializer,推荐使用JdkSerializationRedisSerializer: #序列化java对象(即只有实现了Serializable接口的对象才能被序列化),redis中存储的值不可读StringRedisSerializer: #用于序列化字符串,不适用于对象

对比后存储key统一使用StringRedisSerializer,存储value统一使用Jackson2JsonRedisSerialize最为方便 . 

下面即是对redisTemplate进行增强(注入新的redisTemplate,spring自动注入的redisTemplate会自动失效):

@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){    RedisTemplate<String, Object> template = new RedisTemplate<>();    template.setConnectionFactory(factory);    // 使用Jackson2JsonRedisSerialize 替换默认序列化(默认采用的是JDK序列化)    Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer =new Jackson2JsonRedisSerializer<>(Object.class);    //序列化对象互转对象设置    ObjectMapper om = new ObjectMapper();    //设置任何对象的任何信息都可见      om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);    //对所有非final类型的元素进行序列化    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);    jackson2JsonRedisSerializer.setObjectMapper(om);    //设置redis存储value序列化方式    template.setValueSerializer(jackson2JsonRedisSerializer);    //设置redis存储key序列化方式    template.setKeySerializer(new StringRedisSerializer());    template.setHashKeySerializer(new StringRedisSerializer());    //调用此方法对上面设置的信息进行初始化    template.afterPropertiesSet();    return template;}

至此,springboot1.5.9集成redis结束,如有疑问,欢迎留言讨论.

欢迎关注个人订阅号:Java技术宝典 ,及时获取最新分享.

db6131536b4249a5df79119d43bf1304.png

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值