1. 为什么Redis必须设置密码:这是踩过坑之后的真心话
先说一个我自己经历过的场景:某次为了方便本地联调,把开发环境里的Redis bind设成了0.0.0.0,然后仗着“内网没关系”就没设密码。结果某天早上发现6379端口被捅,数据库里的键值全被换成了一串比特币地址。虽然那只是个缓存服务,数据没了能重建,但排查过程极其痛苦,得一遍遍回捞日志、清依赖,最后还得跟运维解释为什么生产配置里藏着这么个裸奔实例。从那以后,凡是部署在非本机回环地址上的Redis,我第一件事就是先把requirepass写好,再谈别的。
其实Redis默认配置里也有保护机制:只要没显式配置bind和requirepass,它就是只允许127.0.0.1访问的,而且开启protected-mode之后,只能本机连接。但问题在于,很多人拿到Redis后第一件事就是注释掉bind 127.0.0.1,改成0.0.0.0,为的是让局域网/远程能访问,但又忽略了密码设置——这一下就把默认保护全部绕过了。Redis本身是一款高性能的键值存储,常用于缓存、会话管理、分布式锁等等场景,一旦暴露在不受信网络里,等于给恶意访问者递了一把钥匙,能通过FLUSHALL直接把缓存清空,甚至利用高版本的功能去读主机文件,非常危险。
所以这篇文章就是围绕“Redis设置密码”这件事,把配置文件写法、命令行的动态更新方式、Docker容器里的设置方法、主从复制/哨兵模式下的密码联动,以及客户端连接时容易踩的坑,全部过一遍。不管你是刚装完Redis还没头绪的新手,还是已经部署了一套但密码配得不够完善的老手,下面的内容都值得从头到尾看一遍。我自己从裸奔到规范配置,中间踩过的坑,能帮你少走不少弯路。
提示:如果你只是在单机本地做开发,Redis可以只监听127.0.0.1且不设密码,但只要你把地址暴露给局域网,或者开了Docker端口映射,就必须立刻把密码加上。
2. 密码配置前的准备工作:先搞懂这几个概念,后面才不会乱
2.1 requirepass、masterauth、acl,这些参数到底是干什么的
Redis的密码体系不是只有“一个requirepass”这么简单。先说最先接触的requirepass,它设置的是Redis服务端对普通客户端的访问密码。用户连接后第一次执行命令前,必须先通过AUTH验证,否则会报NOAUTH Authentication required。这是最经典也最好用的一种密码设置方式,一视同仁,所有客户端共用一个密码。
但如果你是做主从复制或者哨兵集群的,光配requirepass还不够。从节点需要向主节点发起同步,从节点本身也要被客户端连接,如果只设了masterrequirepass,从节点的配置里还要额外指定masterauth,用来让从节点在连接主节点时自动完成身份认证。这里很多人会忽略,结果明明两边都设置了同样的requirepass,从节点却一直报MASTER auth failed。原因就是masterauth没有配。
另外,Redis 6.0之后引入了完整的ACL(Access Control List)体系,acl相关命令可以做到更细粒度的权限控制,比如给不同业务线分配不同用户名和密码,限制能访问的keys和能执行的命令。虽然ACL更强大,但对于大多数中小项目来说,用requirepass加上合理防火墙策略已经够用了。这篇文章以requirepass为核心,后面也会提一句主从场景下masterauth怎么联动。
2.2 先找到你的Redis配置文件,别用错了目录
在动手之前,第一步是确认Redis的配置文件在哪里。一般Linux环境通过apt或yum安装的Redis,配置文件在/etc/redis/redis.conf;从官网下载源码编译安装的,默认在安装目录下,比如/usr/local/redis/redis.conf。Windows下的Redis没有官方版本,通常用的是微软或厂商移植的版本,配置文件名多为redis.windows.conf或redis.windows-service.conf。
我第一次没看准配置文件,直接用redis-server启动,发现设置死活不生效,后来才发现自己改的是redis.conf,但实际启动时用的是redis.windows.conf,文件都找错了。所以记住一个原则:启动的时候尽量显式指定配置文件路径,例如redis-server /path/to/redis.conf,这样才确定自己改的是不是真正生效的那份配置。可以先用redis-cli info server看下config_file字段,或者直接执行redis-cli config get dir,它返回的是配置文件所在目录,方便定位。
实操心得:修改配置文件之前,先用命令
redis-cli CONFIG GET requirepass看一下当前生效的密码是什么,避免误以为没配过,结果手一滑覆盖了原有规则。
3. 三种最常用的Redis设置密码方式:场景各不相同
3.1 方式一:直接改redis.conf,重启后永久生效
先说最正规的方式。打开Redis配置文件,找到# requirepass foobared这一段,把注释去掉,改成你自己的密码。比如:
# 将这一行取消注释并修改 requirepass yourStrongPassword123改完之后保存,重启Redis进程。注意重启方式要看你的Redis是怎么运行的。如果是systemd管理的服务,用systemctl restart redis;如果是直接用redis-server启动的,先Ctrl+C停掉再重新启动。重启之后用客户端连接,不带密码直接执行命令会报:
127.0.0.1:6379> get username (error) NOAUTH Authentication required.需要先执行auth yourStrongPassword123,然后再操作。这个方案的好处是永久生效,不管进程重启多少次都有效。缺点是必须重启Redis,如果是生产环境且缓存里有大量需要持久化的数据,就会有一小段不可用窗口。所以我一般会在业务低峰期操作,或者先用下面第二种方式动态修改,等确认没问题再写回配置文件。
3.2 方式二:用CONFIG SET动态修改,不用重启就能临时顶上去
如果你不想立刻重启Redis,或者只是想在线上临时改个密码应急,可以直接在命令行里执行:
redis-cli -p 6379 127.0.0.1:6379> CONFIG SET requirepass "newPasswordForNow" OK执行这条命令后,新密码会立刻生效,不用重启。客户端重新连接时就要用新密码了。但这里有个坑:CONFIG SET只是内存中的临时修改,Redis重启之后又会恢复到配置文件里的旧值,或者恢复为无密码状态。所以动态修改只适合临时应急。如果你确认这个密码要长期使用,建议随后再执行CONFIG REWRITE把当前配置持久化到配置文件里:
127.0.0.1:6379> CONFIG REWRITE OK这个命令会把Redis内存中生效的配置写回配置文件,前提是Redis配置文件路径可得且Redis对它有写权限。有些容器环境运行用户权限不足,会报Rewriting config file: Permission denied,需要先确认权限问题。
注意:
CONFIG SET设置密码的瞬间,当前连接不会被强制断开,但你下一次执行命令时会发现居然还能执行,这是Redis为了兼容性做的处理。不过,新建连接必须用新密码,否则认证不通过。
3.3 方式三:Docker容器里的Redis设密码,别在容器里瞎折腾
现在很多人的Redis都装在Docker容器里,尤其是配合Kubesphere、Kubernetes这类编排平台跑的时候,Redis通常作为一个Pod服务存在。使用Docker启动Redis镜像时,最推荐的做法是把密码作为命令行参数直接传进去,而不是进容器里面改配置。
例如用redis:7.0镜像启动一个带密码的容器,可以这样:
docker run -d --name redis-auth \ -p 6379:6379 \ -v /data/redis:/data \ redis:7.0 --requirepass yourStrongPassword123注意这里的--requirepass是传给Redis服务端的启动参数,不是Docker的容器参数。它会覆盖镜像内的默认配置,作为Redis进程启动时读取的命令行选项。启动后验证一下:
docker exec -it redis-auth redis-cli # 连接后执行 auth 127.0.0.1:6379> auth yourStrongPassword123 OK如果你有自定义的配置文件,建议通过挂载方式带入容器,例如:
docker run -d \ -v /myconf/redis.conf:/usr/local/etc/redis/redis.conf \ redis:7.0 redis-server /usr/local/etc/redis/redis.conf这时候密码就写在宿主机上的/myconf/redis.conf里了,容器内只是引用。不要在容器里手动改配置文件再commit镜像,那是最差实践——临时性修改极易丢失,而且镜像会越积越臃肿。
4. 客户端连接时的那些坑:密码设好了,连不上才是真崩溃
4.1 redis-cli里如何带密码连接,别漏了空格和引号
设置完密码之后,最基础的就是命令行连接。两个常见写法,一个是先连接再认证:
redis-cli -h 192.168.1.100 -p 6379 192.168.1.100:6379> AUTH yourPassword OK另一个是直接在连接时带上-a参数:
redis-cli -h 192.168.1.100 -p 6379 -a yourPassword ping PONG但这种写法有个安全风险:命令参数会出现在进程列表里,别人通过ps工具能看到完整密码。所以对生产环境,我更推荐你先登录,然后执行AUTH,或者使用交互式方式。在脚本中如果必须用-a,可以考虑通过环境变量传参,但至少不要写在明文脚本里长期保存。
另外,如果你的密码里包含特殊字符,比如#、@、!、空格,那么直接命令行里写-a 'my#password'要注意单引号转义,避免被shell误解。最保险的做法还是设置一些无特殊字符的密码,省得各种客户端里配置起来出一堆问题。
4.2 RedisDesktopManager / Another Redis Desktop Manager连接时Connection参数该怎么填
可视化客户端现在用得最多的是RDM(RedisDesktopManager)和Another Redis Desktop Manager,连接界面主要有Host、Port、Password几个字段。填的时候注意:密码对应的是Password,如果有ACL用户,还要在User字段填用户名,默认是default。很多人会在这里把密码填成AUTH xxx,或者把整个命令填进去,结果认证永远失败。
我第一次用RDM连接的时候,填了Host、Port,Password框里一旦填错直接被拒绝,其实只要密码正确,默认用户就叫default,不需要再额外填用户名。连接成功后,可以点击CLI标签页执行命令,验证是否成功。
实操心得:RDM连接时如果提示
WRONGPASS invalid username-password pair,八成是密码打错了或者没注意到密码前后有空格。少数情况是Redis的ACL配置中把default用户的密码改了,这时候需要填对用户名和密码,不是只填密码能蒙混过关的。
4.3 Python、Spring Boot连接Redis时的密码配置方式
Python连接Redis标准做法是用redis-py库:
import redis r = redis.Redis( host='192.168.1.100', port=6379, password='yourStrongPassword123', decode_responses=True ) r.set('hello', 'world') print(r.get('hello'))如果使用连接池,则把密码参数放到连接池初始化时:
pool = redis.ConnectionPool( host='192.168.1.100', port=6379, password='yourStrongPassword123', db=0 ) r = redis.Redis(connection_pool=pool)Java Spring Boot中使用Redis也很常见,通常在application.yml或application.properties里直接指定:
spring: redis: host: 192.168.1.100 port: 6379 password: yourStrongPassword123 timeout: 3000ms如果Redis没有设密码,这个password字段可以不写;一旦设了密码,就必须同步修改这里,否则应用启动时会报Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: NOAUTH Authentication required。
这里有个容易踩的坑:如果你在Spring Cloud Config中或者K8s ConfigMap里统一管理配置,改完Redis密码后,一定要记得去更新配置中心里的那一份,否则服务重启后用的是旧密码,直接连不上。
5. 主从复制、哨兵、集群模式下,密码配置还会“传染”
5.1 主从复制:从库需要配masterauth,否则复制链路直接断掉
如果Redis以主从模式运行,主库开启了requirepass,从库必须配置masterauth,否则从库连接主库执行PSYNC时会被拒绝。具体报错信息会在Redis日志里出现:
MASTER aborted replication with an error: NOAUTH Authentication required.或者:
1:M 01 Jan 2024 00:00:00.000 * MASTER <-> REPLICA sync started 1:M 01 Jan 2024 00:00:00.000 * Non blocking connect for SYNC fired the event. 1:M 01 Jan 2024 00:00:00.000 * Master replied to PING, replication can continue...然后紧接着就是认证失败。解决方式是在从库的配置文件里加上:
replicaof <主库IP> <主库端口> masterauth <主库认证密码>如果从库也配置了requirepass,那是给连接从库的客户端用的,跟复制链路无关。这个区分一定要搞清楚:requirepass管客户端,masterauth管主从之间。很多人在从库上设置requirepass后,忽略了masterauth,导致复制断开。
5.2 哨兵(Sentinel):别忘在哨兵配置里指定auth-pass
哨兵模式下,哨兵本身要连接到主从节点来监控状态,所以也要能通过认证。在sentinel.conf里,除了标准的监控配置,还需要使用sentinel auth-pass指定Redis的密码:
sentinel monitor mymaster 192.168.1.100 6379 2 sentinel auth-pass mymaster yourStrongPassword123这个masterauth的值必须跟主从节点上的requirepass保持一致。如果哨兵监控的节点有不同密码(很少见),分别指定也行,但最好保持一致以减少维护成本。还要注意,哨兵在故障切换后,会把从节点提升为主节点,这个过程如果从节点没有设置masterauth,新的主节点可能又变成无密码模式,导致复制和客户端连接全部出问题。所以配置主从密码时,最好所有节点统一处理。
5.3 集群模式:每个节点都要设密码,客户端需要统一配置
Redis Cluster模式更讲究,每个节点(包括主节点和从节点)都需要在配置文件中设置相同的requirepass和masterauth,这样集群内部节点互相通信、迁移槽位时才能通过认证。如果集群中某个节点忘了设置,会发现集群状态为fail,cluster nodes里某些节点标记为fail?,检查日志全是认证异常。
实际操作中,我一般会写好一个统一配置片段,批量分发到每个节点:
requirepass chongfuPassw0rd! masterauth chongfuPassw0rd!密码相同的情况下,集群通信不会有额外压力。如果密码不同,redis-cli --cluster fix会让你在修复过程中输多次密码,非常麻烦。所以集群场景的密码策略一定是“统一、固定、少改”。
6. 常见问题与排查技巧实录:这些情况我都遇到过
6.1 设置完密码后远程客户端还是连不上
这个现象很常见。服务端设置了密码,并且bind 0.0.0.0也配了,但远程客户端连接时要么直接超时,要么报Connection refused。先排除防火墙和云安全组有没有放行6379端口;然后查看Redis当前绑定的地址是不是只有127.0.0.1,用命令:
redis-cli -a yourPassword config get bind返回127.0.0.1 -::1说明Redis根本没监听外部地址。这是很多新手容易踩的坑:光加密码没改bind,等于对外不可达。把bind改成0.0.0.0或者指定你的内网地址,然后重启。
还有一种情况是protected-mode yes导致的。即使你没有配置requirepass,只要bind的不是127.0.0.1或者设置了密码,protected-mode就会拒绝来自非本机的连接。所以,如果你的Redis实例需要远程访问,要么设密码,要么把protected-mode设为no,但强烈推荐的做法是设密码,别关保护。
6.2 明明密码正确的,却提示WRONGPASS / invalid password
先看用户名。Redis 6以后的ACL默认用户名是default,如果你在可视化工具里填了自定义用户名,很可能就不是默认用户。如果自定义ACL用户没配好,密码对也会报错。再检查密码是否被shell、配置文件转义了。例如requirepass abc$123,在shell中执行CONFIG SET时如果没加引号,$123会被当成shell变量替换。这时候我们看到的密码根本不是实际密码,看起来像密码正确,但实际可能被改过了。最好用单引号包裹再执行。
如果是通过环境变量或配置文件引入的密码,尤其要留意末尾换行符\n,这在很多部署脚本里会莫名被附加进密码中,导致客户端看起来密码没错,就是报错。排查方式是在Redis里执行CONFIG GET requirepass,直接看服务端存储的密码值,和客户端配置的做对比。
实操心得:我曾经排查过一个线上问题,应用程序服务一直重连不上Redis,结果发现是运维在K8s ConfigMap里写密码时,YAML自动在末尾加了个空格,导致密码变成“123456 ”。这种问题靠肉眼看配置根本发现不了,一定得用三引号包裹或者严格检查。
6.3 忘记Redis密码了,紧急恢复怎么做
先说一个应急操作:如果Redis当前没有开启持久化,或者你确认可以接受丢少量数据,可以直接修改配置文件,重启Redis,这是一个简单的办法。但如果Redis已经在跑,且你不想丢内存数据,可以临时绕过密码验证吗?除了重启并用--requirepass参数重新设置外,没有更优雅的办法。因为AUTH是Redis核心认证逻辑,无法在不重启的情况下绕过去。
实际操作中我常用的恢复步骤:
- 先看进程是怎么启动的,找到配置文件路径;如果是systemd管理,查
/etc/systemd/system/redis.service里的ExecStart。 - 停掉Redis进程:
systemctl stop redis或kill对应PID。 - 编辑配置文件,去掉
requirepass行或改成已知密码。 - 再启动Redis,恢复服务。
- 登录后立刻用
CONFIG SET requirepass "newPassword"设置新密码,再执行CONFIG REWRITE写回。
这种方式的前提是你有操作系统权限,能改配置文件。真到了那种Docker容器内一改配置就起不来的情况,就只能删容器重新挂了,所以容器场景一定要把密码配置固化在启动参数或挂载配置中。
6.4 排查技巧:学会看Redis日志,别瞎猜
密码相关故障最快定位方式是看日志。默认Redis日志输出到stdout,如果通过systemd运行,用journalctl -u redis -f查看;如果是容器,用docker logs redis-container。出现NOAUTH字样就是认证未通过;出现MASTER auth failed就是从库连接主库认证失败;出现DENIED Redis is running in protected mode是受保护模式拒绝了远程连接。把这些关键词记下来,排查的时候直接按图索骥。
我以前总喜欢在客户端反复试命令,直到看到日志里明晃晃写着Permission denied我才反应过来是配置问题。经验告诉我:出问题先看服务端日志,再看客户端日志,最后才去猜代码配置。
7. 密码管理和安全加固的几条建议
设置完密码不等于安全就完事了。Redis的密码只是第一道门,后面还有几个细节值得一起做。密码本身要够长够随机,不要用123456这种一眼就能猜到的密码。可以用工具生成,比如Linux下:
openssl rand -base64 24生成的字符可能包含/、+、=,这些在URL或配置解析时容易出问题。我更推荐生成32位十六进制字符串,用:
openssl rand -hex 16这样的密码全是字母和数字,各客户端配置都友好。密码定期更换也建议纳入运维计划,尤其是人员变动频繁的开发环境。换密码时先改服务端,再改客户端,最后确认客户端生效,再观察一段时间,不要一股脑全改了才想起来有发现漏改。
另外,强制建议启用Redis的rename-command来禁用或重命名危险命令,比如FLUSHALL、FLUSHDB、KEYS、SHUTDOWN等。配置文件里可以有如下片段:
rename-command FLUSHALL "" rename-command FLUSHDB "" rename-command KEYS "some_prefix_keys"这样即使密码泄露,攻击者也无法直接清空整个Redis。注意重命名KEYS后,你的可视化客户端可能也要调整,有些客户端会依赖KEYS命令做key扫描,重命名后它们会无法工作。所以要根据实际使用场景权衡。
另一个容易被忽略的点是:不要让Redis监听公网。如果只是内网服务,用防火墙把6379端口限制在业务网段内。密码是安全层之一,网络隔离是更重要的一层。双重保障才能应对端口扫描、内网渗透等风险。
8. 写在最后:一次规范配置,换来整晚好觉
从裸奔到规范配置,Redis设置密码这件事,操作上不复杂,难的是想清楚每个模式的联动关系。单机版改requirepass就够了;主从要加masterauth;哨兵还要配sentinel auth-pass;集群则统一所有节点的密码。每一步都验证一遍,不能想当然。
我个人在实际操作中的体会是:宁可多做几次CONFIG GET确认,也别直接拿生产环境赌。尤其改配置之前,先用redis-cli -p 6379 INFO REPLICATION记一下当前主从角色,避免在从库上改完密码却说“主库为什么连接失败”。如果用了Docker部署,尽量把密码写在启动参数或挂载配置文件中,这样容器重建后不会丢失配置。
最后再分享一个小技巧:在配置中心或脚本里管理Redis密码时,明文写难免会有泄漏风险,有条件的话建议用Vault一类的密钥管理服务,配合环境变量注入,这样即使日志被打出来,也不会直接暴露密码本体。但如果项目比较轻,密码靠人工管理,那至少保证它的独立性和随机性,不要跟数据库、操作系统账号的密码复用同一个。一次规范配置,换来的是整晚好觉,值得花那十分钟。