Docker搭建Redis集群,并用Spring Boot连接Redis集群

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 连接池启动总会有连接不上的问题

    • 添加依赖

      		
              <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);
      

你可能感兴趣的:(redis,docker,spring,boot)