sentinel模式基本可以满足一般生产的需求,具备高可用性。但是当数据量过大到一台服务器存放不下的情况时,主从模式或sentinel模式就不能满足需求了,这个时候需要对存储的数据进行分片,将数据存储到多个Redis实例中。cluster模式的出现就是为了解决单机Redis容量有限的问题,将Redis的数据根据一定的规则分配到多台机器。
cluster可以说是sentinel和主从模式的结合体,通过cluster可以实现主从和master重选功能,所以如果配置两个副本三个分片的话,就需要六个Redis实例。因为Redis的数据是根据一定规则分配到cluster的不同机器的,当数据量过大时,可以新增机器进行扩容。
使用集群,只需要将redis配置文件中的cluster-enable配置打开即可。每个集群中至少需要三个主数据库才能正常运行,新增节点非常方便。
多个redis节点网络互联,数据共享
所有的节点都是一主一从(也可以是一主多从),其中从不提供服务,仅作为备用
不支持同时处理多个key(如MSET/MGET),因为redis需要把key均匀分布在各个节点上,并发量很高的情况下同时创建key-value会降低性能并导致不可预测的行为
支持在线增加、删除节点
客户端可以连接任何一个主节点进行读写
这时候需要修改redis的配置文件,并把默认注释的下面选项放开:
cluster-enabled yes
节点是否支持集群,可以通过下面命令来查看:
# 查看集群
cluster nodes
如果没有配置,则出现如下错误:
127.0.0.1:6379> cluster nodes
ERR This instance has cluster support disabled
# 运行节点1
docker run -itd --name redis9090 -p 9090:6379 -v D:/app/redis/redis.conf:/usr/local/etc/redis/redis.conf:rw redis:6.0-rc redis-server /usr/local/etc/redis/redis.conf
# 运行节点2
docker run -itd --name redis9091 -p 9091:6379 -v D:/app/redis/redis.conf:/usr/local/etc/redis/redis.conf:rw redis:6.0-rc redis-server /usr/local/etc/redis/redis.conf
# 运行节点3
docker run -itd --name redis9092 -p 9092:6379 -v D:/app/redis/redis.conf:/usr/local/etc/redis/redis.conf:rw redis:6.0-rc redis-server /usr/local/etc/redis/redis.conf
这时候再运行cluster nodes,则会显示如下界面:
# 查看集群
cluster nodes
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.8.0</version>
</dependency>
spring.redis.cluster.nodes=127.0.0.1:9090,127.0.0.1:9091,127.0.0.1:9092
spring.redis.timeout=60000
spring.redis.lettuce.pool.max-wait=-1
spring.redis.lettuce.pool.max-active=300
spring.redis.lettuce.pool.max-idle=100
spring.redis.lettuce.pool.min-idle=20
package com.shenmazong.demorediscluster;
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;
@SpringBootTest
class DemoRedisClusterApplicationTests {
@Autowired
StringRedisTemplate stringRedisTemplate;
@Test
void contextLoads() {
}
@Test
void testRedisSet() {
stringRedisTemplate.opsForValue().set("david", "123");
}
@Test
void testRedisGet() {
String david = stringRedisTemplate.opsForValue().get("david");
System.out.println(david);
}
}
当然不可能一帆风顺,第一次运行可能出现如下错误:
org.springframework.data.redis.RedisSystemException: Redis exception; nested exception is io.lettuce.core.cluster.PartitionSelectorException: Cannot determine a partition for slot 2180.
如果出现上面错误,可以通过如下命令来修复一下:
redis-cli --cluster fix 172.17.0.2:6379
redis-cli --cluster fix 172.17.0.3:6379
redis-cli --cluster fix 172.17.0.4:6379
由于redis的节点使用的是docker运行的,所以如果在一台机器上,则需要使用docker的内部ip,docker的内部ip可以通过如下命令获取:
docker inspect redis9092
再次运行,应该能够正常运行。