SpringBoot+Redisson连接使用Docker部署的Redis集群

时间:2025-03-22 07:15:17

文章目录

  • 集群
    • 创建网络
    • 创建集群
  • Redisson
    • 导入依赖
    • 配置
    • 测试
  • 问题

集群

使用Docker配置redis集群。

  1. 创建网络
  2. 编写配置文件
  3. 运行容器
  4. 构建集群

创建网络

网络名称redis(可自行更换)。

docker network create -d bridge --subnet 172.180.0.0/16 --gateway 172.180.0.1 redis

#查看网络状态
docker network ls
docker network inspect redis

创建集群

其余三个过程可以使用Shell脚本完成,rmredis. sh(移除容器),(创建配置文件,运行容器,创建集群)。从主机对应端口号6371~6376 (可自行配置)。


文件路径可以修改。

for port in $(seq 1 6)
do
    echo "remove redis0${port}"
    docker rm -f redis0${port}
    rm -rf /home/zhangzhibo/redis/node-${port}
done


将主机ip修改成你的,路径同样可修改。

#!/bin/bash
for port in $(seq 1 6)
do
#创建配置文件
    echo "this value is $port"
    mkdir -p /home/zhangzhibo/redis/node-${port}/conf
    touch /home/zhangzhibo/redis/node-${port}/conf/
cat << EOF > /home/zhangzhibo/redis/node-${port}/conf/
#端口 
port 6379
#非保护模式 
protected-mode no
#启用集群模式 
cluster-enabled yes
cluster-config-file nodes-637${port}.conf
#超时时间 
cluster-node-timeout 15000
#集群各节点IP地址,记得修改为你的ip地址
cluster-announce-ip 主机ip
#集群节点映射端口 
cluster-announce-port 637${port}
#集群总线端口 
cluster-announce-bus-port 1637${port}
#开启aof持久化策略 
appendonly yes
#后台运行
#daemonize yes
#进程号存储
pidfile /var/run/redis_6379.pid
#外部访问
bind 0.0.0.0
#日志
logfile "redis${port}.log"
#密码
#requirepass 123456
EOF

#创建容器
	echo "create redis0${port}"
#不使用docker部署 redis-server /home/zhangzhibo/redis/node-${port}/conf/
#使用docker部署
    docker run -d --name redis0${port} -p 637${port}:6379 -p 1637${port}:16379 --network redis --ip 172.180.0.1${port} -v /home/zhangzhibo/redis/node-${port}/data:/data -v /home/zhangzhibo/redis/node-${port}/conf/:/etc/redis/ redis redis-server /etc/redis/

done

echo "create cluster"
#此条语句执行的前提是主机上也安装了redis。
#没安装,注释掉随机进入一个容器执行即可。
redis-cli --cluster create 主机ip:6371 主机ip:6372 主机ip:6373 主机ip:6374 主机ip:6375 主机ip:6376 --cluster-replicas 1

Redisson

使用redisson连接集群。

导入依赖

只需要导入redisson的spring-boot-starter,这个依赖中含有redis启动器。

 		<dependency>
            <groupId></groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.17.3</version>
        </dependency>

配置

只需要在/yml/yaml中编写配置即可。可查看RedissonAutoConfiguration官方自动配置类,该配置类有调用RedissonProperties与RedisProperties,可根据两个配置类的属性进行配置。

(如有需求可对RedissonAutoConfiguration内的方法进行重写)

spring:
  redis:
    timeout: 6000
    cluster:
      max-redirects: 3
      nodes:
        - redis://服务器主机ip:6371
        - redis://服务器主机ip:6372
        - redis://服务器主机ip:6373
        - redis://服务器主机ip:6374
        - redis://服务器主机ip:6375
        - redis://服务器主机ip:6376
    lettuce:
      pool:
        max-active: 1024 # 连接池最大连接数(默认为8,-1表示无限制 如果pool已经分配了超过max_active个jedis实例,则此时pool为耗尽)
        max-wait: 10000 #最大等待连接时间,单位毫秒 默认为-1,表示永不超时,超时会抛出JedisConnectionException
        max-idle: 10
        min-idle: 5
      shutdown-timeout: 100

RedissonAutoConfiguration中创建了两个Template,RedisTemplate<Object, Object>与StringRedisTemplate。可以看到这两个并不能满足我们的需求,我们需要的泛型是<String, Object>,同时还要在redis数据库中查看数据时不出现乱码,所以要自行配置并对存储的数据进行序列化处理。

当然也可以使用他给的RedisTemplate<Object, Object>,使用@Autowired注入便可使用。

在使用@Autowired注入RedisTemplate<Object, Object>过程中,可能会报错提示“无法通过类型注入”。可以使用@Resource或者 @Autowired+ @Qualifier(value=“XXX”)。

@Configuration
public class RedisTemplateConfig {

    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new
                Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        StringRedisSerializer stringRedisSerializer = new
                StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

}

测试

测试时创建了User类,同时实现了序列化接口。

注入,测试

	@Autowired
    RedisTemplate<String, Object> redisTemplate;

    @Test
    void springbootRedisson() {
        RedisConnection connection = 
                        Objects.requireNonNull(redisTemplate.getConnectionFactory()).getConnection();
        connection.flushDb();
        User user = new User("zhangzhibo", 22);
        redisTemplate.opsForValue().set("user",user);
        System.out.println(redisTemplate.opsForValue().get("user"));
    }

问题

场景:

使用docker run … -d redis redis-server /…/ 运行容器后,使用docker ps查看容器创建成功但并没有启动。

解决方法:

文件中的daemonize参数为yes导致,修改/home/redis/redis-master/ 中的daemonize 为no 。docker本身就是后台运行的,daemonize为yes两者会冲突


场景:

在项目中集成Redis,连接单机Redis时。Redis运行在docker中,在确认路径、代码编写没问题下连接失败

解决办法:

  1. 查看有没有启动Redis服务器。

  2. redis的配置(或)中连接超时时间(毫秒)中设置不能为0,一般修改如下:=5000。

  3. protected-mode yes 改为 protected-mode no (即该配置项表示是否开启保护模式,默认是开启,开启后Redis只会本地进行访问,拒绝外部访问)。

  4. 注释掉 bin127.0.0.1 即 #bin 127.0.0.1 (ps: 指定 redis 只接收来自于该 IP 地址的请求,如果不进行设置,那么将处理所有请求)。

  5. 如果在Redis中没有配置requirepass ,那么在(或)中就不要写。


场景:

在集群测试阶段,无法正常运行。并伴有“正确”的cluster-config-file输出,主节点(master)无法连接。

解决办法:

查看cluster-config-file输出,其中的ip地址为127.0.0.1或者自定义的网络地址。redisson会根据配置的网络ip进行连接。(使用Jedis连接也会出现同样的错误)

要更改配置文件

cluster-announce-ip 主机ip
cluster-announce-port 容器内6379端口对应的主机端口
cluster-announce-bus-port 容器内16379端口对应的主机端口

容器内不一定是6379,依据你的配置而定。