使用Docker安装的redis,springboot连接redis,经常过一段时间就从redis取值失败,报这个错误Redis exception; nested exception is io.lettuce.core.RedisException: java.io.IOException: 远程主机强迫关闭了一个现有的连接。
1. 报错原因
spring中配置的超时时间应该大于tcp的存活时间,否则tcp连接还存活着,spring以为已经超时,又去创建,就会强制之前的连接关闭。
2.解决方案
修改redis.conf文件中的tcp-keepalive数值。就是一次连接tcp的存活时间
但是通过reids安装的有时候配置文件可能会不生效,所以使用docker重装redis,确保配置文件可以生效
修改springboot 连接redis的超时时间,需要这个时间大于tcp-keepalive的时间
3.重装Redis确保配置文件生效
拉取最新镜像
docker pull redis
创建文件夹
cd /home mkdir redis/conf mkdir redis/data
写入redis配置文件。redis.conf
1. cd /home/redis/conf 2. vim redis.conf
配置文件内容
##节点端口 port 6379 ##允许任何来源 #bind 0.0.0.0 bind 47.99.149.92 120.244.10.31 ## 是为了禁止公网访问redis cache,加强redis安全的。它启用的条件,有两个:1) 没有bind IP 2) 没有设置访问密码 启用后只能够通过lookback ip(127.0.0.1)访问Redis cache,如果从外网访问,则会返回相应的错误信息 protected-mode no ##开启持久化模式 appendonly yes appendfilename appendonly.aof #开启混合持久化 aof-use-rdb-preamble yes # 文件达到1m时进行重写,然后如果文件大小增长了一倍,也会触发重写。 auto-aof-rewrite-min-size 1mb auto-aof-rewrite-percentage 100 ##AOF 文件和 Redis 命令是同步频率的,假设配置为 always,其含义为当 Redis 执行命令的时候,则同时同步到 AOF 文件,这样会使得 Redis 同步刷新 AOF 文件,造成缓慢。而采用 evarysec 则代表 ## 每秒同步一次命令到 AOF 文件。 appendfsync everysec #pidfile redis.pid #进程pid文件,加port以示区分 pidfile /data/redis/data/redis_6379.pid # 后台运行 ---- docker中使用后台运行将无法启动容器(应该是容器无法检测后台运行进程) # daemonize yes databases 20 tcp-keepalive 20 #redis初始密码 requirepass 1234
启动容器
1. 2. docker run -d -p 6379:6379 --name my_redis --privileged=true -v /home/redis/conf/red
通过这种方式可以指定redis的配置文件,确保配置文件中的tcp-keepalive生效
4. 配置springboot连接redis
##redis配置 spring.redis.database=0 ### 服务器地址,默认为localhost spring.redis.host=172.1.1.1 ### 链接端口,默认为6379 spring.redis.port=6379 ### redis密码默认为空 spring.redis.password=123456 #处理连接超时等 如 java.io.IOException: 远程主机强迫关闭了一个现有的连接。 #Spring Boot 从 2.0版本开始,将默认的Redis客户端Jedis替换为Lettuce spring.redis.lettuce.pool.max-active=8 spring.redis.lettuce.pool.max-wait=-1ms spring.redis.lettuce.pool.max-idle=5 spring.redis.lettuce.pool.min-idle=0 spring.redis.timeout=30000ms # 关闭超时时间 spring.redis.lettuce.shutdown-timeout=100