使用 docker 搭建 Redis 集群
打开防火墙并开放指定端口
systemctl start firewalld
firewall-cmd --permanent --zone=public --add-port=7001-7006/tcp
#重新加载配置
firewall-cmd --reload
#查看开放的端口
firewall-cmd --permanent --zone=public --list-ports
下载redis镜像
docker pull redis
创建linux中redis容器集群文件夹(进入目录:cd /opt/docker/redis/cluster)
mkdir -p /opt/docker/redis/cluster
创建redis的配置模板文件:redis-cluster.tmpl(用于生成redis.conf)
vim redis-cluster.tmpl
#端口
port ${PORT}
#非保护模式
protected-mode no
#启用集群模式
cluster-enabled yes
cluster-config-file nodes-6379.conf
#超时时间
cluster-node-timeout 15000
#集群各节点IP地址,记得修改为你的ip地址
cluster-announce-ip 192.168.235.128
#集群节点映射端口
cluster-announce-port ${PORT}
#集群总线端口
cluster-announce-bus-port 1${PORT}
#开启aof持久化策略
appendonly yes
#后台运行
#daemonize yes
#进程号存储
pidfile /var/run/redis_${PORT}.pid
#外部访问
bind 0.0.0.0
#集群加密
masterauth 123456
requirepass 123456
定义redis网络
docker network create redis-net
在/opt/docker/redis/cluster下生成redis的conf和data目录,并生成redis.conf配置文件,创建6个redis容器并启动
#!/bin/bash
#在/opt/docker/redis/cluster/下生成conf和data目标,并生成配置信息
for port in `seq 7001 7006`;
do
mkdir -p ./${port}/conf && PORT=${port} envsubst < ./redis-cluster.tmpl > ./${port}/conf/redis.conf && mkdir -p ./${port}/data;
done
#创建6个redis容器
for port in `seq 7001 7006`;
do
docker run -d -it -p ${port}:${port} -p 1${port}:1${port} -v /opt/docker/redis/cluster/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf -v /opt/docker/redis/cluster/${port}/data:/data --privileged=true --restart always --name redis-cluster-${port} --net redis-net --sysctl net.core.somaxconn=1024 redis redis-server /usr/local/etc/redis/redis.conf;
done
#查找ip
for port in `seq 7001 7006`;
do
echo -n "$(docker inspect --format '{{ (index .NetworkSettings.Networks "redis-net").IPAddress }}' "redis-cluster-${port}")":${port}" ";
done
#换行
echo -e "\n"
#输入信息
read -p "请把输入要启动的docker容器名称,默认redis-cluster-7001:" DOCKER_NAME
#判断是否为空
if [ ! $DOCKER_NAME ];
then DOCKER_NAME='redis-cluster-7001';
fi
#换行
echo -e "\n"
#进入容器
docker exec -it redis-cluster-7001 /bin/bash
批量删除、重启镜像
for port in `seq 7001 7006`; do \
docker stop redis-cluster-${port};
docker rm redis-cluster-${port};
done
for port in `seq 7001 7006`; do \
docker restart redis-${port};
done
在容器(任意)内执行
redis-cli -a 123456 --cluster create 172.20.0.2:7001 172.20.0.3:7002 172.20.0.4:7003 172.20.0.5:7004 172.20.0.6:7005 172.20.0.7:7006 --cluster-replicas 1
查看集群信息
redis-cli -a 123456 -p 7001 -c
cluster nodes
cluster info
容器外查看集群状态
docker ps
SpringBoot连接Redis集群
引入 commons-pool2 连接池启动总会有连接不上的问题
添加依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
<version>3.3.0version>
dependency>
<dependency>
<groupId>org.redissongroupId>
<artifactId>redisson-spring-boot-starterartifactId>
<version>3.16.2version>
dependency>
配置文件 application.properties
#redis集群配置
spring.redis.timeout=5000
spring.redis.password=123456
spring.redis.cluster.max-redirects=3
spring.redis.cluster.lettuce.pool.max-idle=10
spring.redis.cluster.lettuce.pool.max-wait=5000
spring.redis.cluster.lettuce.pool.max-active=200
spring.redis.cluster.lettuce.pool.min-idle=3
spring.redis.cluster.nodes=192.168.235.128:7001,192.168.235.128:7002,192.168.235.128:7003,192.168.235.128:7004,192.168.235.128:7005,192.168.235.128:7006
redis 配置类:RedisConfigProperties.java
package com.example.demo.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author Capital Letters
* @title: RedisConfigProperties
* @projectName oj-homework
* @description: TODO
* @date 2022/5/189:45
*/
@Component
@ConfigurationProperties(prefix = "spring.redis")
public class RedisConfigProperties {
private Integer timeout;
private Integer database;
private Integer port;
private String host;
private String password;
private cluster cluster;
public static class cluster {
private List<String> nodes;
public List<String> getNodes() {
return nodes;
}
public void setNodes(List<String> nodes) {
this.nodes = nodes;
}
}
public Integer getTimeout() {
return timeout;
}
public void setTimeout(Integer timeout) {
this.timeout = timeout;
}
public Integer getDatabase() {
return database;
}
public void setDatabase(Integer database) {
this.database = database;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public RedisConfigProperties.cluster getCluster() {
return cluster;
}
public void setCluster(RedisConfigProperties.cluster cluster) {
this.cluster = cluster;
}
}
RedissonConfig.java(集群模式)
package com.example.demo.config;
import org.redisson.Redisson;
import org.redisson.config.ClusterServersConfig;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
/**
* @author Capital Letters
* @title: RedissonConfig
* @projectName oj-homework
* @description: TODO
* @date 2022/5/189:48
*/
@Configuration
public class RedissonConfig {
@Autowired
private RedisConfigProperties redisConfigProperties;
/**
* 集群模式-添加redisson的bean
* @return
*/
@Bean
public Redisson redisson() {
//redisson版本是3.5,集群的ip前面要加上“redis://”,不然会报错,3.2版本可不加
List<String> clusterNodes = new ArrayList<>();
for (int i = 0; i < redisConfigProperties.getCluster().getNodes().size(); i++) {
clusterNodes.add("redis://" + redisConfigProperties.getCluster().getNodes().get(i));
}
Config config = new Config();
ClusterServersConfig clusterServersConfig = config.useClusterServers()
.addNodeAddress(clusterNodes.toArray(new String[clusterNodes.size()]));
//设置密码,如果没有密码,则注释这一行,否则启动会报错
clusterServersConfig.setPassword(redisConfigProperties.getPassword());
return (Redisson) Redisson.create(config);
}
}
RedissonConfig(单机模式)
package com.example.demo.config;
import org.redisson.Redisson;
import org.redisson.config.ClusterServersConfig;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
/**
* @author Capital Letters
* @title: RedissonConfig
* @projectName oj-homework
* @description: TODO
* @date 2022/5/189:48
*/
@Configuration
public class RedissonConfig {
@Autowired
private RedisConfigProperties redisConfigProperties;
/**
* redis://host:port
*/
private static final String REDIS_ADDRESS = "redis://%s:%s";
/**
* 集群模式-添加redisson的bean
* @return
*/
@Bean
public Redisson RedissonConfig() {
Config config = new Config();
config.useSingleServer().setAddress("redis://localhost:6379").setDatabase(redisConfigProperties.getDatabase());
config.useSingleServer().setAddress(String.format(REDIS_ADDRESS, redisConfigProperties.getHost(), redisConfigProperties.getPort()))
.setDatabase(redisConfigProperties.getDatabase())
.setPassword(redisConfigProperties.getPassword());
return (Redisson) Redisson.create(config);
}
}
RedisTemplateConfig
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* @author Capital Letters
* @title: RedisTemplateConfig
* @projectName oj-homework
* @description: RedisTemplateConfig
* @date 2022/5/189:51
*/
@Configuration
public class RedisTemplateConfig {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 自定义的string序列化器和fastjson序列化器
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// jackson 序列化器
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// kv 序列化
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setValueSerializer(jsonRedisSerializer);
// hash 序列化
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(jsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
测试
@Resource
private RedisTemplate<String, Object> redisTemplate;
redisTemplate.opsForValue().set("test", "test", 300, TimeUnit.SECONDS);