redis的集羣模式和哨兵模式
redis中集羣模式
redis集羣模式配置支持3.0及以上的版本。目的提高redis的可用性,但是隻能保證一定程度的高可用。
redis-cluster原理
Redis 集羣有16384個哈希槽,每個key通過CRC16校驗後對16384取模來決定放置哪個槽.集羣的每個節點負責一部分hash槽,舉個例子,比如當前集羣有3個節點,那麼:
- 節點 A 包含 0 到 5500號哈希槽.
- 節點 B 包含5501 到 11000 號哈希槽.
- 節點 C 包含11001 到 16384號哈希槽.
這種結構無論添加刪除或者改變某個節點的哈希槽的數量都不會造成集羣不可用的狀態。
因爲這種key分佈在不同的節點,所以不能使用多keys的操作。(其實也可以變相的實現,但是在高負載的情況下存在風險)。
redis-cluster的主從複製模型
爲了實現一定程度的高可用,比如某個節點掛掉的情況下,服務仍然能夠正常使用。redis使用了主從複製模型,例如創建三個節點的集羣A,B,C,在集羣創建的時候或者過段時間爲三個節點,添加從節點A1,B1,C1.此時整個集羣有三個master節點和三個slave節點。A節點down掉的情況,集羣推舉A1爲主節點繼續服務。當然,如果A,A1都掛掉的情況,集羣則無法使用。所以這也是爲什麼集羣只能保證一定程度的高可用。
redis集羣安裝配置
redis-cluster在Java中的應用
這裏列出spring-boot中的配置方法和spring中的配置方式兩種方式,根據自己的情況使用。(親測可用)
環境:
jdk:1.8
spring:
spring-boot:2.0.6
jedis:2.9.0(這個版本支持集羣密碼的配置,更早的版本不支持)
spring中的配置
Spring-boot中的配置
pom.xmL中引入jedis2.9依賴:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
application.properties中redis的配置:
# Redis服務器地址
spring.redis.clusterNodes=ip:port,ip1:port1
# Redis服務器連接端口
spring.redis.port=6379
# Redis服務器連接密碼(默認爲空)
spring.redis.password=XXXX
# 連接超時時間(毫秒)
spring.redis.timeout=3600
# 連接池最大連接數(使用負值表示沒有限制)
spring.redis.jedis.pool.max-active=8
# 連接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.jedis.pool.max-wait=-1
# jedis超時
spring.redis.jedis.shutdown-timeout=100
# 連接池中的最大空閒連接
spring.redis.jedis.pool.max-idle=8
# 連接池中的最小空閒連接
spring.redis.jedis.pool.min-idle=0
接下來將這些配置讀取到Spring 容器中:
/**
* @Author:chenglitao
* @Description:
* @Date:2018/11/7 16:15
*/
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
/**
*@Author:chenglitao
*@Description:
*@Params:redis配置類
*@Date:2018/11/28 16:46
*
*/
@Configuration
public class JedisRedisConfig {
@Value("${spring.redis.clusterNodes}")
private String clusterNodes;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.port}")
private int port;
@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-wait}")
private long maxWaitMillis;
}
然後配置RedisCluster:
/**
* @Author:chenglitao
* @Description:
* @Date:2018/11/7 16:13
*/
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import java.util.HashSet;
import java.util.Set;
/**
*@Author:chenglitao
*@Description:
*@Params:
*@Date:2018/11/28 16:44
*
*/
@Configuration
public class RedisClusterConfig {
@Autowired
private JedisRedisConfig redisProperties;
@Bean
public JedisCluster jedisCluster() {
String[] serverArray = redisProperties.getClusterNodes().split(",");
//獲取服務器數組,逗號分隔
Set<HostAndPort> nodes = new HashSet<>();
for (String ipPort : serverArray) {
String[] ipPortPair = ipPort.split(":");
nodes.add(new HostAndPort(ipPortPair[0].trim(), Integer.valueOf(ipPortPair[1].trim())));
}
GenericObjectPoolConfig config = new
GenericObjectPoolConfig();
config.setMaxTotal(3);
return new JedisCluster(nodes, redisProperties.getTimeout(), 1000, 100, redisProperties.getPassword(), config);//需要密碼連接的創建對象方式,如果沒有密碼,就使用沒有密碼的方法,這裏有很多重載的構造方法。
}
}
最後,寫test方法測試下就ok了。
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import redis.clients.jedis.JedisCluster;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Autowired
private JedisCluster jedisCluster;
@Test
public void contextLoads() {
jedisCluster.set("aa", "111");
String aa = jedisCluster.get("aa");
System.out.println(aa);
}
}
當然,在開發中需要封裝基礎的工具類操作。下面是基本的操作的封裝,根據自己的需要修改即可。