一:搭建Redis集群
1.集群规划
- 原理:简单理解Redis-cluster的slot, redis集群原理总结()
- 本案例在同一台服务器上用不同端口代表不同的Redis服务器(伪分布式集群),
主节点 192.168.5.134:8001 192.168.5.134:8002 192.168.5.134:8003
从节点 192.168.5.134:8004 192.168.5.134:8005 192.168.5.134:8006
最后再单独分别搭建一个主节点和从节点
2.集群配置
Redis集群管理工具redis-trib.rb 倚赖Ruby环境,而由于版本问题需要先安装RVM
- 安装RVM
gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
\curl -sSL https://get.rvm.io | bash -s stable
source /etc/profile.d/rvm.sh
source ~/.bashrc
source ~/.bash_profile
- 查看有哪些Ruby版本
rvm list known
- 安装Ruby
rvm install 2.5.1
- 安装Redis倚赖
gem install redis
- 下载redis 4.0.11,新建redisCluster文件夹,并上传到该文件夹中
mkdir redisCluster
tar -zxvf redis-4.0.11.tar.gz
cd redis-4.0.11
make MALLOC=libc
make install
- 安装后将src下的redis-trib.rb复制到redisCluster中
cd src
cp /root/redisCluster/redis-4.0.11/src/redis-trib.rb /root/redisCluster
- 在redisCluster下创建从8001到8006六个文件夹,将redis目录下的redis.conf分别复制到六个文件夹中,并修改如下,其中cluster-config-file和port中的800*要对应文件夹名修改,在此本人的配置文件是修改前四行,再添加后四行
#bind 127.0.0.1
protected-mode no
port 8001
daemonize yes
cluster-enabled yes
cluster-config-file nodes-8001.conf
requirepass 123@456
masterauth 123@456
- 在redis-4.0.11下分别启动六个服务
redis-server ../8001/redis.conf
redis-server ../8002/redis.conf
redis-server ../8003/redis.conf
redis-server ../8004/redis.conf
redis-server ../8005/redis.conf
redis-server ../8006/redis.conf
- 启动后在redisCluster下对redis-tirb.rb进行修改,找到下面的这行内容
@r = Redis.new(:host => @info[:host], :port => @info[:port], :timeout => 60)
- 添加密码参数并修改,其中123@456就是各个实例登陆的密码:
@r = Redis.new(:host => @info[:host], :port => @info[:port], :timeout => 60,:password=>"123@456")
- 创建集群
./redis-trib.rb create --replicas 1 192.168.5.134:8001 192.168.5.134:8002 192.168.5.134:8003 192.168.5.134:8004 192.168.5.134:8005 192.168.5.134:8006
- replicas表示每个主节点slave的数量,每个集群在创建的过程中都会分配主机和从机,每个集群在创建的过程中都会分配一个唯一的id并分配到一段slot. 集群创建成功后,进入redis-4.0.11中,登陆任意redis实例:
redis-cli -p 8001 -a 123@123 -c
- -p 表示端口, -a表示要登陆的集群的密码,-c表示以集群的方式登陆,登陆成功后cluster info 查询集群信息,通过cluster nodes查询节点的信息,能看到节点是master还是slave,如果是slave那么master的节点是多少,如果是master slot的范围是多少
auth 123@456
cluster info
cluster nodes
- 添加一个主节点
- 将8001复制一份并重命名8007,并按上文更改redis.conf,在redis-4.0.11下运行该节点
redis-server ../8007/redis.conf
,将该节点添加到集群中./redis-trib.rb add-node 192.168.5.134:8007 192.168.5.134:8001
- 登陆一个节点,并查看节点详细信息,可以发现8007节点已经被添加成功,但新实例却没有被分配slot,现需要在redisCluster下执行以下命令,连接上任一个实例,重新分配slot
./redis-trib.rb reshard 192.168.5.134:8001
- 执行命令的过程中会有三个选项,第一个是分配多少个slot,此处配置1000个,第二个是分配给谁,此处要填写8007的id(执行cluster nodes后例如下图中的第一列既是),第三个是从谁那里拿slot,此处填写8001的id也可以填写all让所有的实例均摊,配置完成后可看到节点已添加成功
8 . 添加从节点
- 复制一份8008节点,并配置好redis.conf,配置好后启动该实例,启动后在redisCluster下执行命令:
./redis-trib.rb add-node --slave --master-id 73821b4e942686f3a240aff9b6a53efa0e627599 192.168.5.134:8008 192.168.5.134:8001
- –master-id 填写上节新建的8007节点id,后面填写从节点地址和任意一个实例的地址,创建完后登陆任意一个实例可以看到新添加的从节点
9 . 删除节点
- 如果要删除一个从节点那么如下命令即可完成
./redis-trib.rb del-node 192.168.5.134:8001 abb0f48704c8a38ff6c0b4ee9d5f9df74a042131
- 其中中间是任意一个实例,后面是一个要删除实例的id,但要删除一个有slot的节点,就需要按照第七步中将slot全部分配出去,才能删除成功
二:整合Spring Boot
1.创建一个Spring Boot项目,并添加以下倚赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2.使用application.yum进行配置
spring:
redis:
cluster:
ports:
- 8001
- 8002
- 8003
- 8004
- 8005
- 8006
- 8007
- 8008
host: 192.168.248.144
poolConfig:
max-total: 8
max-idle: 8
max-wait-millis: -1
min-idle: 0
- 创建RedisConfig完成对Redis的配置
@Configuration
@ConfigurationProperties("spring.redis.cluster")//声明配置文件的前缀,并注入到下面的三个属性中
public class RedisConfig {
List<Integer> ports;
String host;
JedisPoolConfig poolConfig;
//设置redis登陆密码即redis登陆信息
@Bean
RedisClusterConfiguration redisClusterConfiguration() {
RedisClusterConfiguration configuration = new RedisClusterConfiguration();
List<RedisNode> nodes = new ArrayList<>();
for (Integer port : ports) {
nodes.add(new RedisNode(host, port));
}
configuration.setPassword(RedisPassword.of("123@456"));
configuration.setClusterNodes(nodes);
return configuration;
}
@Bean
RedisTemplate redisTemplate() {
RedisTemplate redisTemplate = new RedisTemplate();
redisTemplate.setConnectionFactory(jedisConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
return redisTemplate;
}
@Bean
StringRedisTemplate stringRedisTemplate() {
StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(jedisConnectionFactory());
stringRedisTemplate.setKeySerializer(new StringRedisSerializer());
stringRedisTemplate.setKeySerializer(new StringRedisSerializer());
return stringRedisTemplate;
}
//根据redisClusterConfiguration创建JedisConnectionFactory,
//再根据JedisConnectionFactory创建上面的RedisTemplate和StringRedisTemplate
@Bean
JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory(redisClusterConfiguration(),poolConfig);
return factory;
}
//getter setter
}
- 创建实体类和Controller
public class Book implements Serializable {
private String name;
private String author;
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", author='" + author + '\'' +
'}';
}
//setter getter
}
@RestController
public class BookController {
@Autowired
RedisTemplate redisTemplate;
@Autowired
StringRedisTemplate stringRedisTemplate;
@GetMapping("/test1")
public void test1() {
ValueOperations ops = redisTemplate.opsForValue();
Book book = new Book();
book.setName("水浒传");
book.setAuthor("施耐庵");
ops.set("b1", book);
System.out.println(ops.get("b1"));
ValueOperations<String, String> ops2 = stringRedisTemplate.opsForValue();
ops2.set("k1", "v1");
System.out.println(ops2.get("k1"));
}
}
- 测试
- 访问 http://localhost:8080/test1 ,控制台打印
- 登入一个实例查看数据
- 如图可发现在任一个实例上redisCluster可以重定向到响应的实例上去