Redis 常见问题
[1]服务启动后,无法连接 Redis 抛错
背景
Dante Cloud 基础服务在启动时必须要连接 Redis,连接成功后才能正常运行。
目前涉及到 Redis 的内容,主要包括两部分:
- 常规的数据缓存特别像 Session、验证码一类的临时缓存,这一类缓存根据场景以及实现要求的不同,有些会直接使用 Redis;
- 数据共享缓存,像权限数据、CRUD 数据等缓存,这一类缓存除了要实现数据缓存的目的之外,还要解决缓存数据在多服务、多实例环境下数据共享同步等问题。因此采用的是 JetCache 多级缓存组件。
因本项目更倾向于贴近 Spring 生态,尽量使用 Spring 生态主打或推荐的相关组件。所以不管是直接访问 Redis 还是集成 JetCache,底层数据访问客户端组件均使用的是 lettuce。也正因为如此,Spring 生态相关组件自身的不足也会体现在 Dante Cloud 中。
问题原因
服务启动后无法连接 Redis,除了网络问题导致的无法连接以外,最主要的诱因就是:Redis 密码中包含特殊字符。
包含特殊字符的密码导致 Redis 无法连接,原因大概出自两方面:
- 一方面是 Spring Boot 基本规范导致。Spring Boot Yaml 对特殊字符是有处理要求的,Yaml 配置信息中,如果包含以下特殊字符必须要进行转义
:, {, }, [, ], ,, &, *, #, ?, |, -, <, >, =, !, %, @, `
- 另一方面是基础组件自身处理机制导致。有些组件是采用 uri 的方式进行 Redis 连接配置,而有些组件使用 ip + 端口等方式处理。所以就可能存在,同样的密码,使用 Jedis、Redisson 等组件是正常的,换到 Dante Cloud 所使用的 lettuce 就不正常;甚至可能使用 lettuce 是正常的,换到 JetCache 又会有问题。
解决方法
方法一
这个方法最直接最简单,就是修改 Redis 密码,去掉密码中的某个或者全部特殊字符。
提示
很多人都期望通过增加 Redis 密码复杂度来提升 Redis 的安全性。不可否认这确实能提升一定的安全性,但是毕竟 Redis 的密码安全机制太过简单,所以个人建议不要太过于依赖于此,网络层面或者物理层面保证 Redis 的相对隔离才能靠谱。(换句话说 Redis 密码复杂度更像是心理安慰,不能从本质上提升多大的安全性,所以就不要太纠结密码中要不要包含特殊字符的问题)
方法二
对密码中的特殊字符进行转义,以保证可以正确被读取和使用。
- 在 Spring Boot Yaml 方面,如果存在特殊字符就需要对密码字符串进行转义,例如下例中密码包含了特殊字符 “#”,这种写法是会出现运行错误问题的
spring:
#data source connection
datasource:
url: jdbc:mysql://localhost:3306/vaquarkhan
username: rootadmin
password: root#
需要对特殊字符进行转义:
可以用引号包裹字符串进行转义
"root#"
或者用反斜杠
root\#
完整的例子
spring:
#data source connection
datasource:
url: jdbc:mysql://localhost:3306/vaquarkhan
username: rootadmin
password: "root#"
- 对于像 JetCache 一样使用 uri 进行 Redis 连接配置的,那么特殊字符的转义,就要参考 url.encode 的方式,例如:
符号 | - | 转义结果 | 符号 | - | 转义结果 |
---|---|---|---|---|---|
空格 | - | %20 | / | - | %2F |
" | - | %22 | : | - | %3A |
# | - | %23 | ; | - | %3B |
% | - | %25 | < | - | %3C |
& | - | %26 | = | - | %3D |
( | - | %28 | > | - | %3E |
) | - | %29 | ? | - | %3F |
+ | - | %2B | @ | - | %40 |
, | - | %2C | \ | - | %5C |
一个完成的参考示例,需要转义,spring Data redis 使用'',而 jetcache 使用 URL 转义
spring:
application:
redis:
password: "123@!"
jetcache:
remote:
test:
uri: redis://123%40%21@${spring.redis.host}:${spring.redis.port}/${spring.redis.database}
poolConfig:
minIdle: 5
maxIdle: 20
maxTotal: 50
[2]本地 Redis 使用 127.0.0.1 可以访问,使用 IP 地址无法访问
Redis 默认只允许通过 127.0.0.1 访问,这是其自身的安全防护机制。如果想要使用 IP 地址进行访问,需要将其保护设置打开。
- Windows 版
找到redis.windows.conf
配置文件
将
protected-mode
参数改为 no。注释掉
bind 127.0.0.1
重启 redis 服务

- Linux
linux 对应的是
redis.conf
文件修改还是和 windows 一样
修改完成重启服务
[3]io.lettuce.core.RedisCommandExecutionException: NOAUTH Authentication required
出现该错误,是由于 Redis 中设置密码,而代码中未读到 Redis 密码或配置文件中没有配置密码导致的。
- 解决办法:
- 首先用
Redis
客户端,比如:redis-desktop-manager
,进行Redis
的连接测试。如果无法连接,那么请检查密码输入是否正确,本地网络等相关环境;如果可以正常连接,请进行下一步。 - 检查
Nacos
中,Redis
相关配置是否配置了密码。一定要注意格式,检查格式缩进是否正确,yaml
配置“:”后面是否空了一格。如果确定配置正确,请进行下一步。 - 检查服务是否可以正常访问到
Nacos
服务器,是否可以正确读取Nacos
中配置。
以上操作均确保无误应该就可以正常使用了,如果还有问题,那么就请尽可能的准备详尽的信息,在 Gitee 中提Issue
[4]NOAUTH HELLO must be called with the client already authenticated, otherwise the HELLO AUTH < user >
使用spring boot data redis
链接redis sentinel
集群,会报此错。
原因是因为redis sentinel
集群的sentinel
配置文件没有配置密码,sentinel
配置密码的方式和 redis 的密码配置方式一样,配置文件中加上requirepass <密码>
就行。
另外,sentinel
中的sentinel auth-pass <master> <pass>
不是给sentinel
配置密码,而是sentinel
链接redis master
的密码