docker搭建redis集群
-
使用 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集群
-
SpringBoot连接Redis集群
-
引入 commons-pool2 连接池启动总会有连接不上的问题
-
添加依赖
<!--redis依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- redis.client.jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.3.0</version> </dependency> <!-- redisson-springboot --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> <version>3.16.2</version> </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);
-