1. 程式人生 > >spring boot配置同時支援單機和叢集redis

spring boot配置同時支援單機和叢集redis

正式環境都是用叢集版redis,開發用的單機版,領導要求通過配置檔案來確定是單機還是叢集,由於單機版已經實現了,那麼準備就在單機版基礎上進行開發,然後發現spring boot1.2版本已經比較老,就升級版本,由於升級了spring boot版本,對應其他配置也進行了修改。最終修改的配置如下:

pom.xml

<properties>
	<java.version>1.8</java.version>
	<spring.version>4.3.9.RELEASE</spring.version>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>1.5.8.RELEASE</version>
</parent>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
       <!--原來是spring-boot-starter-redis-->
</dependency>
<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>2.9.0</version>
</dependency>

redis.properties檔案基本沒有變:

# REDIS (RedisProperties) 
# Redis伺服器地址(叢集用逗號分隔)
#spring.redis.host=xxx.xxx.xxx.xxx:xxxxx
spring.redis.host=xxx.xxx.xxx.xxx:xxxxx,xxx.xxx.xxx.xxx:xxxxx
# Redis伺服器連線密碼(預設為空)
spring.redis.password=123456
# 連線超時時間(毫秒)
spring.redis.timeout=2000
spring.redis.max-redirects=8

注意:host變成ip:port,叢集多個ip和埠用“,”分割,為什麼這樣寫spring框架中RedisClusterConfiguration類中就是這樣分割。看一下原始碼:

//RedisClusterConfiguration類:
private static final String REDIS_CLUSTER_NODES_CONFIG_PROPERTY = "spring.redis.cluster.nodes";  //預設是配置這樣的
……
public RedisClusterConfiguration(PropertySource<?> propertySource) {

	notNull(propertySource, "PropertySource must not be null!");

	this.clusterNodes = new LinkedHashSet<RedisNode>();
        //有spring.redis.cluster.nodes配置,分割這個屬性,新增node
	if (propertySource.containsProperty(REDIS_CLUSTER_NODES_CONFIG_PROPERTY)) {
		appendClusterNodes(commaDelimitedListToSet(propertySource.getProperty(REDIS_CLUSTER_NODES_CONFIG_PROPERTY)
				.toString()));
	 }
         ……
	}
//函式會呼叫,用","分割:
public static String[] commaDelimitedListToStringArray(String str) {
	return delimitedListToStringArray(str, ",");
}
//然後用":"分割組裝成RedisNode
private void appendClusterNodes(Set<String> hostAndPorts) {

	for (String hostAndPort : hostAndPorts) {
		addClusterNode(readHostAndPortFromString(hostAndPort));
	}
}

private RedisNode readHostAndPortFromString(String hostAndPort) {
	String[] args = split(hostAndPort, ":");

	notNull(args, "HostAndPort need to be seperated by  ':'.");
	isTrue(args.length == 2, "Host and Port String needs to specified as host:port");
	return new RedisNode(args[0], Integer.valueOf(args[1]).intValue());
}

 在cacheconfig類中變成這樣的:

@Bean
	public RedisClusterConfiguration getClusterConfiguration() {
		if (host.split(",").length > 1) {
                        //如果是host是叢集模式的才進行以下操作
			Map<String, Object> source = new HashMap<String, Object>();

			source.put("spring.redis.cluster.nodes", host);

			source.put("spring.redis.cluster.timeout", timeout);

			source.put("spring.redis.cluster.max-redirects", redirects);
              //在原始碼的註釋中可以看到是這樣配置,以為這樣寫就不用在Connection中不用在認證,後來確定太天真了
            
            source.put("spring.redis.cluster.password", password);

			return new RedisClusterConfiguration(new                 
                MapPropertySource("RedisClusterConfiguration", source));
		}  else {
			return null;
		}
	}

	@Bean
	public JedisConnectionFactory jedisConnectionFactory() {
		if (host.split(",").length == 1) {
			JedisConnectionFactory factory = new JedisConnectionFactory();
			factory.setHostName(host.split(":")[0]);
			factory.setPort(Integer.valueOf(host.split(":")[1]));
			factory.setPassword(password);
			factory.setTimeout(timeout);
			return factory;
		} else {
			JedisConnectionFactory jcf = new JedisConnectionFactory(getClusterConfiguration());
			jcf.setPassword(password); //叢集的密碼認證
			return jcf;
		}

	}
//這樣改造之後,redisTemplate模板就不用改了,之前寫的redisUtil類也不用變了