news 2026/9/18 14:46:01

Redis 6.0+ ACL 权限拆分实战:从共用密码到最小权限

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis 6.0+ ACL 权限拆分实战:从共用密码到最小权限

凌晨两点半被电话叫醒,说测试环境那台 Redis 里几个业务的数据全没了。登上去一看,dbsize归零,INFOtotal_connections_received里有个陌生的客户端地址。查到最后原因很朴素:某位同学本地调试时脚本里写死了一句FLUSHALL,而线上和测试共用了同一套连接配置,那个实例上跑着五个业务的数据。事后复盘,所有人都在问同一个问题——为什么任何一个连上来的客户端,都有权限把整个实例清空?答案就是那时候我们还在用requirepass,整个实例只有一个密码,谁拿到密码谁就是超级管理员。

这件事之后我把手上所有 Redis 都升到了 6.0 以上,开始系统性地用 ACL 做权限拆分。这篇就聊聊Redis 6.0+ 的 ACL 机制,从规则语法、版本差异,到真实落地时踩过的坑,尽量写得能直接照着做。不管你是刚开始接触 Redis 的运维,还是已经在线上跑了几十个实例的老手,只要你还在用"一个密码打天下"的方式管 Redis,这些内容应该都能省你点事。

1. 共用密码这件事,到底危险在哪里

1.1requirepass时代的三条硬伤

requirepass这个配置项解决的是"谁能连上来"的问题,它本质上只是一个门禁开关:要么全有权限,要么连不上。这在只有一个业务、一套代码、一个团队维护的小规模场景里完全够用,但只要有第二个使用方加入,问题就立刻暴露出来。

第一条硬伤是权限无法区分。缓存业务和会话业务连的是同一个实例,理论上缓存业务只该读写cache:*前缀的键,会话业务只该读写session:*,但requirepass给不了这个粒度。任何一个业务拿到密码,就等于拿到了FLUSHDBCONFIG SETDEBUGSCRIPT这些命令的完全使用权。

第二条硬伤是轮换成本极高。密码要换就得所有使用方同时改配置、同时重启或重连,中间任何一方没跟上就是全量故障。所以现实中很多团队的密码一用就是三年,配置文件在 Git 里躺得明明白白,等于没设。

第三条硬伤是没有审计线索。出事了只能看到"有人执行了FLUSHALL",但MONITOR里看不到是哪个业务、哪个账号干的,因为所有人共用一个身份。事后追责基本靠猜。

1.2 ACL 带来的不只是一个密码字段

很多人第一次接触 ACL,以为它就是"可以建多个密码",这个理解偏差挺大。ACL 引入的是一个完整的用户(user)概念,每个用户身上挂了四类属性:能不能登录、能用哪些命令、能碰哪些键、能订阅哪些频道。这四件事互相独立,可以任意组合。

拿一个具体例子感受一下区别。以前你给日志归档服务一个密码,它理论上可以执行CONFIG SET appendonly yes、可以SWAPDB、可以DEBUG SLEEP,你完全拦不住。用了 ACL 之后,你可以把它限制成只能执行+get +mget +set,只能访问archive:*这一批键,连KEYS都用不了。这个服务就算代码写崩了、被注入了、配置文件泄了,它能造成的最大破坏就是archive:*里的数据被改坏,而不是整个实例。

一个常见的认知误区:觉得 ACL 是"大厂才需要的东西"。实际上判断标准很简单——只要你这个 Redis 实例有两个以上互不相关的使用方,或者有任何一个使用方不应该拥有全量权限,ACL 就值得上。

1.3 什么样的实例该立刻动手

我给自己的判断标准列了三条,满足任意一条我就开始拆权限:实例上跑着超过一个业务的数据;实例上存着任何一份丢了会疼的数据(比如会话、订单中间态);实例的连接来源跨越了多个团队或供应商

反过来说,如果这个 Redis 纯粹是你本地开发用的,或者就是某个服务的私有缓存、删了也无所谓,那继续用requirepass甚至不设密码都没什么大问题,别为了"技术正确"给自己加无谓的维护负担。

2. 把 ACL 规则拆开看:用户、命令、键、频道

2.1 一条规则字符串的完整骨架

ACL 的规则全部是以空格分隔的短标记拼接出来的,ACL SETUSER接收的就是这一串东西。我把常用标记整理成了一张表,看一遍就能记住大半:

标记含义备注
on/off用户是否启用禁用的用户连不上
nopass任意密码都能通过等价于不要密码
>password追加一个明文密码存储时会转成 SHA256
<password移除指定明文密码必须完全匹配
#hash用 SHA256 哈希值添加密码适合配置流水线
!hash移除指定哈希密码同上
~pattern键模式,读写都允许多个模式之间是"或"
%R~pattern只读键模式7.0 起支持
%W~pattern只写键模式7.0 起支持
allkeys等价于~*
resetkeys清空已配置的键模式想"减权限"只能靠它
&pattern频道模式6.2 起支持
allchannels等价于&*
resetchannels清空频道权限6.2 起新建用户默认就是这个
+command允许某条命令支持+config|get这种子命令写法
-command禁止某条命令
+@category/-@category按类别批量放行/禁止类别名用ACL CAT
allcommands等价于+@all
nocommands等价于-@all
reset把用户重置回初始关闭状态常用作规则串的第一个词

这里有个新手最容易困惑的点:ACL 规则是增量叠加的,你能加权限但不能"减一点"~app:* ~order:*是允许两个前缀,但如果你想从~*退回到只允许app:*,没有"去掉某条键模式"的语法,只能resetkeys之后把想要的重新加一遍。命令权限也是同理,+@all -@dangerous里的-之所以有效,是因为它在+@all之后的顺序上生效,而不是撤销了+@all

2.2 命令权限:+@all -@dangerous是省事的起手式

命令有几百条,一条条白名单写既不现实也容易漏。Redis 把命令按功能打了标签,用ACL CAT能看到全部类别,常见的包括readwritestringhashlistsetsortedsetstreamkeyspaceadmindangerousfastslowblockingtransactionscriptingconnectionpubsubbitmapgeohyperloglog

我最常用的起手式是:

ACL SETUSER app_user on >xxx resetkeys ~app:* -@all +@read +@write -@dangerous

拆开说:-@all先把所有命令关掉,+@read +@write打开读写(这两个类别已经覆盖了绝大多数数据操作命令),-@dangerous再明确挡掉危险命令。为什么-@all之后-@dangerous还要写?因为顺序上是"先关全量、再加类别、再减类别",这个顺序决定了最终结果。如果你偷懒不写-@all,那些既不属于@read也不属于@write的命令(比如PINGCOMMAND)的权限状态就取决于用户创建时的默认值,容易出意外。

至于@dangerous里到底装了哪些命令,最稳妥的办法是当场查一遍:

ACL CAT dangerous

不同小版本的列表会有细微差别,我不建议凭记忆背。经验上FLUSHALLFLUSHDBSWAPDBCONFIGDEBUGKEYSSHUTDOWNREPLICAOFMIGRATERESTORESORT这些都在里面,但**SCAN不在@dangerous里**,这点后面还会专门讲。

2.3 键模式里的通配符,比你想的更容易写错

键模式用的是 glob 风格的匹配,支持*?[abc]这类写法,多个模式之间是逻辑或。看起来简单,实际写起来有三个坑我必须提醒。

第一个坑是模式不会自动补全~app:*能匹配app:1app:user:1001,但匹配不了app这个键本身,因为app后面没有冒号。如果你的代码里有裸键名,得额外补一条~app。我见过有人写~user:*然后奇怪为什么user这个键老是报权限错误。

第二个坑是规则数量多了以后匹配有性能开销。每个请求都要把所有键模式过一遍,如果你给一个用户挂了上百条细碎模式,在高并发下会有一点影响。所以模式要写得稍微"粗"一点,按业务前缀分组,而不是按每一个键名去列。

第三个坑是键模式挡不住那些"不带键参数"的命令FLUSHALLFLUSHDBKEYSRANDOMKEYDBSIZE这类命令的参数里根本没有键,ACL 的键检查对它们无从下手。这意味着即使你把键模式收得极紧,只要命令权限没关掉,用户依然能执行FLUSHALL把别人的数据清掉。这也是我为什么坚持"键模式 + 命令白名单"两条腿走路,只做其中一个都不够。

还有一点要留意版本差异,%R~%W~这种区分读写的键模式是7.0 才有的,6.0 和 6.2 上只有读写合一的~。如果你在 7.0 上写了%R~report:*,然后回滚到 6.2 的镜像,这条规则会直接加载失败——这类回滚事故我在容器化环境里见过不止一次。

2.4 密码的三种写法与GENPASS

给用户设密码有三种写法,用途完全不同。

>明文密码是最直观的,ACL SETUSER app_user >MyPass123这样。Redis 内部会立刻把它转成 SHA256 存储,ACL LISTACL GETUSER里看到的都是#<64位哈希>,不会回显明文,这一点可以放心。

#哈希值适合 CI/CD 流水线场景。你在密钥管理系统里存好哈希,部署时直接ACL SETUSER app_user #a1b2c3...,配置文件和命令行历史里都不会出现明文。

nopass表示不需要密码。注意它是"任意密码都能通过"而不是"忽略密码校验",效果上接近你把门敞开了,只适合default用户在初始状态下使用。

至于密码怎么生成,别再用123456或者项目名了,Redis 自带一个生成器:

ACL GENPASS ACL GENPASS 128

不带参数默认生成 256 位,输出 64 个十六进制字符;带参数时参数单位是bit,所以ACL GENPASS 128输出 32 个字符。我一般直接用默认的 256 位,反正这东西是一次性生成、存在密钥管理系统里的,长一点没坏处。

3. 从default用户治理到业务账号落地

3.1 先给当前实例拍一张权限现状照

动手改任何东西之前,先看清楚现状。三条命令就够:

ACL LIST ACL WHOAMI ACL GETUSER default

ACL LIST会把所有用户和它们的规则串打印出来。刚装好的 Redis 6.0 上,你会看到类似user default on nopass ~* +@all这样一行——这就是那个"谁都能干任何事"的账号。到了 6.2,这行会变成user default on nopass ~* &* +@all,多了频道的通配。

ACL WHOAMI返回你当前登录的身份,如果你是拿旧密码直连的,多半返回defaultACL GETUSER default的输出更结构化,会分flagspasswordscommandskeyschannels几个字段,7.0 之后还会多一个selectors字段。我习惯在变更前把这些输出存一份到变更单里,回滚的时候对照着看。

3.2 建一个只有读写权限的业务账号

假设有个缓存服务,只碰cache:*这批键,那么一条命令就能建好:

ACL SETUSER cache_svc on >生成出来的密码 resetkeys ~cache:* resetchannels -@all +@read +@write -@dangerous

这条规则里每一段的意图都值得说清楚。on是启用;resetkeys保证从这个用户没有任何键权限的干净状态开始(虽然新建用户本来就是空的,但写上去更保险,也让规则串自解释);~cache:*给键权限;resetchannels在 6.2 以上是新建用户的默认值,写上是防御性的,避免 6.0 升 6.2 之后行为变化;-@all +@read +@write -@dangerous是命令权限的核心。

如果你不确定这个服务还会用到哪些命令,可以先放得松一点,等上线跑一周之后看ACL LOG,把实际用到的命令捞出来再收紧。这种"先观察再收紧"的节奏比一开始就死磕白名单要现实得多。

3.3 只读账号和写受限账号的写法

数据分析和报表服务通常只需要读:

ACL SETUSER report_ro on >密码 resetkeys ~report:* -@all +@read

注意我这里没写-@dangerous,因为-@all已经把所有命令关完了,+@read里本身不含危险命令。KEYS虽然带@read标签,但同时也带@dangerous,那它到底会不会被放行?答案是,因为+@read是正授权,会覆盖先前的-@all。所以如果你想连KEYS都不要,得显式写-keys,并且把-keys放在+@read之后:

ACL SETUSER report_ro on >密码 resetkeys ~report:* -@all +@read -keys -scan -randomkey

这个"后写的规则覆盖先写的"顺序特性,是 ACL 用起来最需要形成肌肉记忆的地方。我给自己定了个书写顺序的固定套路:开关 → 密码 → resetkeys → 键模式 → resetchannels → 命令类别全关 → 命令类别放开 → 单条命令减法。按这个顺序写,基本不会出逻辑歧义。

3.4 验证:别用"能连上"当成功标准

很多人改完权限,用redis-cli -a 密码 PING通了就以为搞定了。PING太基础了,几乎任何配置下都能过。我自己的验证清单是这样的:

redis-cli --user cache_svc --pass 密码 PING redis-cli --user cache_svc --pass 密码 SET cache:test 1 redis-cli --user cache_svc --pass 密码 GET cache:test redis-cli --user cache_svc --pass 密码 SET other:test 1 redis-cli --user cache_svc --pass 密码 FLUSHALL redis-cli --user cache_svc --pass 密码 CONFIG GET maxmemory redis-cli --user cache_svc --pass 密码 KEYS '*'

预期结果是:前三条应该成功,后四条应该全部返回NOPERM开头的错误。把失败用例当成验证清单的一半,这个习惯能帮你提前发现绝大多数权限漏洞。我见过有人只测了成功路径就上线,结果那个账号连CONFIG SET都能执行,等于白拆。

3.5 关掉default用户之前必须确认三件事

default关掉(ACL SETUSER default off)是权限治理的终点,但也是最容易引发全站故障的一步。动手之前必须确认三件事。

第一,是否还有人在用旧密码直连。老的客户端代码里写的都是单密码形式,AUTH的时候会落到default用户上。你需要先在一段时间里用ACL LOG观察有没有auth类型的失败记录,或者用CLIENT LIST看连接的user字段是不是还有default

第二,监控和运维脚本是不是也在用default这一点最容易被忘。你关掉default的瞬间,Prometheus 的 Redis exporter、备份脚本、巡检脚本可能一起报错,然后告警风暴比故障本身还吓人。给这些工具单独建一个monitor_svc账号,只给+@read +info +ping +client|list这类最小集合。

第三,回滚路径是不是通的。关掉default之后如果发现漏了谁,你得能在不重启、不丢数据的前提下恢复。最简单的办法是保留一个admin_svc账号,它有+@all ~* &*的完整权限,default关掉之后用它来救场。这个账号的密码存在离线的地方,不要写进任何代码仓库。

4. 让权限规则活过重启

4.1 内存里的规则和磁盘上的规则是两回事

这是新手最容易栽的坑:你用ACL SETUSER敲进去的规则,只存在于内存里,重启之后就没了。Redis 不会自动把它们写盘。

要让规则持久化,有两条路。第一条是在redis.conf里用user指令静态声明:

user cache_svc on >密码 ~cache:* resetchannels -@all +@read +@write -@dangerous

第二条是启用独立的 ACL 文件:

aclfile /etc/redis/users.acl

然后在users.acl里同样用user开头写规则,配合ACL SAVEACL LOAD做运行时同步。

4.2aclfileredis.conf里的user指令谁说话算数

这两者不是叠加关系,是互斥的。一旦你在配置里启用了aclfileredis.conf中所有的user指令都会被忽略。这个设计我理解是为了避免"两处配置互相打架、排查半天看不出哪条生效"的局面,但对不知情的人来说是个大坑:改了redis.conf加了新用户,重启之后发现用户不见了,因为实际生效的是 ACL 文件。

我踩过这个坑之后的处理方式是项目里只选一种。Kubernetes 环境我倾向用aclfile,因为可以配合 ConfigMap 做声明式管理,改完ACL LOAD热加载,不重启;物理机/虚拟机环境我倾向直接写在redis.conf里,因为变更走配置管理工具,本来就要重启。

4.3ACL SAVE只在配了aclfile时才有意义

ACL SAVE会把当前内存里的用户规则全量覆盖写入 ACL 文件。注意是全量覆盖,不是追加。这意味着如果你手动编辑过 ACL 文件、但还没ACL LOAD,这时候执行ACL SAVE会把你手改的内容冲掉。

正确的手改流程是:改文件 →ACL LOAD→ 用ACL LIST确认生效 → 如果不满意再改文件再ACL LOAD。整个过程中不要穿插ACL SAVE。反过来,如果你是通过ACL SETUSER在线改的,那就ACL SAVE固化。两者不要混着用。

还有一个细节:ACL LOAD如果遇到语法错误的规则会整体失败并保留原有内存状态,不会出现"加载了一半"的中间状态。这一点挺让人放心,但报错信息有时候不够精确,只告诉你第几行有问题,所以改动前最好先在测试实例上验证一遍。

4.4 主从和集群环境下 ACL 是怎么过去的

主从复制时,ACL 相关的命令会跟着命令流同步到从节点,所以在主节点上执行ACL SETUSER通常也会在从节点上生效。但这只覆盖"通过命令修改"的路径,配置文件里的规则不会自动同步——从节点重启之后会读自己的配置,如果它的redis.conf里没有对应的user指令,权限就丢了。

所以主从环境我坚持的做法是:配置层面的 ACL 规则由统一的配置管理下发到所有节点,运行时的临时调整只用在线命令 +ACL SAVE,并且定期用ACL LIST对比主从输出是否一致。写个几行的巡检脚本就够了,diff一下两边输出,不一致就告警。

集群模式更麻烦一点。ACL SETUSER在集群上需要在每个节点分别执行,redis-cli --cluster没有帮你广播 ACL 命令的能力。手动一个个敲十几次是不现实的,我一般写个循环:

for host in 10.0.0.1 10.0.0.2 10.0.0.3; do redis-cli -h $host -p 6379 -a $ADMIN_PASS ACL SETUSER cache_svc on \>$NEW_PASS resetkeys '~cache:*' resetchannels -@all +@read +@write -@dangerous done

注意 shell 里>是重定向符号,必须转义,这个细节能让脚本静默失败很久才发现。

5. 四个翻车现场,从报错文案倒推问题

5.1 命令权限不足和键权限不足,报错长得完全不一样

排查 ACL 问题的第一步是看报错文案。两类权限失败给的信息量差别很大:

失败类型报错特征含义
命令被禁提示信息里带命令名,指出该用户无权执行某命令命令白名单没放行
键被禁提示没有权限访问参数中的某个键键模式没覆盖到
频道被禁提示没有权限访问参数中的某个频道6.2+ 的频道权限问题
身份失败提示认证失败或密码错误用户/密码不对,或用户被off

6.2 之后,报错信息里会带上具体的用户名,这在多账号实例上帮助巨大——你能立刻知道是哪个服务在报错,而不是去猜。如果还在 6.0 上,可以结合ACL LOG里的记录一起看。

5.2 Lua 脚本里KEYS没声明全,ACL 拦不住但集群会拦

这个坑很有意思。EVAL的键权限检查是基于脚本声明的KEYS列表做的,而不是脚本实际访问的键。也就是说,如果你在脚本里写redis.call('GET', 'other:key')但没把它放进KEYS,ACL 的键检查不会拦住它。

单机模式下这会让你的权限隔离形同虚设,集群模式下则会直接报错,因为键不在同一个槽上。所以脚本代码规范里"所有访问的键必须声明在KEYS里"这条,不只是集群兼容性要求,也是 ACL 权限控制的前提。我现在的做法是在代码评审里把这条当成硬性检查项,配合redis.call的静态扫描。

5.3 只放行+config不给+config|get,配置中心集体报错

有些运维面板需要读 Redis 配置来做容量展示,比如看maxmemorymaxmemory-policy。你可能想当然地给了+config,觉得这就够了。但CONFIG是个容器型命令,带SETGETRESETSTATREWRITE等子命令,全放开风险太大。

正确的写法是只放子命令:

ACL SETUSER monitor_svc on >密码 resetkeys +config|get +info +client|list +@read

子命令用竖线分隔。注意在 shell 里执行时竖线同样需要转义或加引号,否则会被当成管道。这个坑的典型症状是:规则看起来加上了,但用户的ACL GETUSER里命令列表是空的,因为命令被 shell 截断了。

5.4 改完密码之后,连接池还捏着旧凭证

这个几乎每个人都遇到过。你在 Redis 上ACL SETUSER app_user >新密码,应用那边配置也改了,重启了几个实例,但总有一部分请求零星报认证失败。原因是连接池里已有的长连接不会因为配置变更而重建

Redis 有些版本支持CLIENT KILL按用户批量断开连接,可以通过CLIENT LIST找到对应用户的连接然后逐个踢掉,强制它们重连。我一般会在改密码流程里加一步:

CLIENT LIST TYPE normal

user字段筛选出目标用户的连接,再CLIENT KILL ID xxx。踢完之后观察监控里的认证失败率是否归零,归零了才算变更完成。

顺带一提,给密码做轮换不要直接"删旧加新"。ACL 支持一个用户挂多个密码,正确姿势是先>新密码加上去,等所有客户端都切换完、旧密码的使用量归零之后,再<旧密码摘掉。这样整个轮换过程对业务完全无感。

6. 客户端侧怎么把用户名带上

6.1redis-cli--user参数

命令行工具从 6.0 开始支持--user

redis-cli -h 10.0.0.1 -p 6379 --user cache_svc --pass 密码

也可以进交互模式之后再切换身份:

AUTH cache_svc 密码 AUTH 密码

两种形式的区别要记住:双参数形式是"用户名 + 密码",单参数形式是"密码",后者会落到default用户上。所以当你把default关掉之后,那些还在用-a单参数的老脚本会立刻全部失败。

6.2 各语言客户端的写法

不同客户端的配置字段名不太一样,我把自己常用几个列出来:

语言/客户端关键配置
Java / Jedis构造Jedis时传入 user 和 password 两个参数
Java / LettuceRedisURI.Builder.redis(host, port)上挂认证信息,用RedisCredentials携带用户名和密码
Spring Boot2.x 用spring.redis.username,3.x 迁到spring.data.redis.username
Go / go-redisredis.Options里的UsernamePassword两个字段
Python / redis-pyRedis(username="app_user", password="xxx"),或 URL 形式redis://app_user:xxx@host:6379/0
Node / ioredis构造参数里的usernamepassword

这里最容易翻车的是 Spring Boot 的版本迁移。2.x 升 3.x 的时候配置前缀从spring.redis变成了spring.data.redis,如果你只改了前缀没注意username字段的对应关系,本地跑得好好的,上线就连不上。这种问题排查起来特别费时间,因为报错只有一句笼统的认证失败。升级前把配置类里的字段逐个对照一遍,比事后查日志划算得多。

6.3 可视化工具和中间件的适配情况

GUI 工具这块差异比较大。新版的管理工具基本都在连接配置里提供了独立的"用户名"输入框,填上就能连。但有些老版本或者轻量工具只有一个"密码"输入框,这种情况下它是走单参数AUTH的,只能连default用户。选型的时候一定要确认工具支不支持独立用户名,否则你辛苦拆出来的权限体系,运维侧根本用不了。

代理类和分片中间件也要注意。有些中间件在转发客户端请求时只透传密码、不透传用户名,这种架构下 ACL 的多用户能力基本用不上,得看中间件自己的权限模型。遇到这种情况,退而求其次的做法是在中间件层做用户到后端实例的映射,也就是每个业务走一个独立的中间件逻辑库,后端按库隔离。

6.4 容器化环境下的凭证注入

Kubernetes 里我一般不把密码写进 ConfigMap,而是用 Secret 挂成环境变量或者文件。启动脚本里读环境变量拼认证参数,密码不会出现在镜像层和命令行历史里。要注意的是环境变量在ps里虽然看不到,但在容器的/proc/1/environ里是明文可见的,如果这个容器有多租户或者能被 exec 进去,风险依然存在。更严格的做法是挂文件,代码里读文件内容。

至于ACL SETUSER这条命令本身,我建议不要放在容器的启动脚本里。原因很实际:多个 Pod 同时启动时会并发执行同一条ACL SETUSER,虽然结果幂等,但混在一起会让ACL LOG和审计日志很难看。更好的做法是把规则维护在 ACL 文件里,通过 ConfigMap 挂载,容器只负责启动时不带任何 ACL 变更。

7. 权限粒度怎么切,几条用过之后才明白的经验

7.1 按业务域切,不要按人切

我一开始的思路是"每个开发一个账号",执行了两周就放弃了。原因很简单:人员会流动,项目会交接,账号和使用者之间的关系维护不起来。后来改成按业务域切,一个服务或者一组强耦合的服务用一个账号,账号名直接用服务名,比如cache_svcsession_svcreport_ro。这样账号的生命周期跟服务的生命周期绑定,服务下线了账号跟着删,不会留下孤儿账号。

粒度上我的经验值是:键模式按前缀切到二级或三级,命令权限按"读 / 读写 / 管理"三档切。再多就没有必要了,维护成本会超过收益。一个实例上 5 到 15 个用户是比较舒服的区间。

7.2 从"全放开"过渡到最小权限的正确节奏

直接上最小权限,几乎一定会出事,因为没人能一次性说清一个跑了三年的服务到底用了哪些命令。我实践下来比较顺的节奏是三步。

第一步,新建一个xxx_svc账号,权限设成~业务前缀:* +@all -@dangerous,先把最危险的那批命令挡掉,这一步就能防住绝大多数事故,而且几乎不会影响业务。

第二步,跑一到两周,定期用ACL LOG看这个用户有没有触发过command类型的拒绝记录。如果一条都没有,说明-@dangerous没有误伤;如果有,看是被哪个命令拦的,评估之后决定是放行还是通知业务改代码。

第三步,根据ACL LOG里实际出现过的命令,把+@all收窄成具体的类别和命令。这一步可以慢慢来,不用一次到位。

这个节奏的价值在于每一步都是可回滚的,出问题改回去就一分钟的事,不会出现那种"改了权限之后业务大面积报错又不知道改哪"的窘境。

7.3ACL LOG是审计的起点,不是终点

ACL LOG会记录最近被拒绝的操作,每条记录包含计数、拒绝原因(命令、键还是频道)、涉及的上下文对象、客户端信息等。它是排查权限问题最直接的工具,但也有两个明显限制。

一是容量有限,它只保留最近若干条,重启会清空。所以生产环境我建议定期把ACL LOG的输出采集出来落到日志系统里,而不是只在排查的时候现查。

二是它只记录被拒绝的操作,不记录成功的操作。想知道某个账号到底用了哪些命令,ACL LOG帮不上忙。这时候要么开MONITOR(生产环境慎用,对性能有影响),要么用INFO commandstats配合按用户的维度去分析。我一般是在新账号接入的观察期开一小段时间的采样,采够了就关掉。

另外,ACL LOG里的记录会按相同的"用户 + 原因 + 对象"聚合计数,所以一条count是 5000 的记录,代表这个操作被拒了 5000 次,而不是 5000 个不同的操作。这个设计在排查高频报错时很省事,但也容易让人误判"只有一条问题"。

最后分享一个我自己一直在用的小习惯:每次给 Redis 做权限变更,我都会在变更前跑一遍ACL LIST把输出存成文件,变更后再跑一遍做diff。这样既能看到这次到底改了什么,出问题的时候也能拿着 diff 直接反向操作回去。比起靠记忆回忆"我刚才是不是少写了个-@all",这个习惯救过我好几次。ACL 这东西,规则写对了很省心,写错了的排查成本却很高,所以在流程上多留一手,比在技术上追求精巧更划算。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 14:42:02

system_prompts_leaks:系统提示词归档、对比与防泄露实践

1. 先搞清楚 system_prompts_leaks 这类项目到底在做什么第一次看到system_prompts_leaks这个名字&#xff0c;很多人的第一反应是"这东西合规吗"。我当初也是这个反应。但把仓库拉下来翻了两天之后&#xff0c;我的判断变了&#xff1a;它本质上是一份公开的提示词工…

作者头像 李华
网站建设 2026/9/18 14:41:46

欧陆EV100变频器说明书解读:铭牌选型与接线故障排查指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 14:41:06

Figma MCP 实战:从设计稿到开发文档的自动化生成指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 14:40:10

程序员英语:将来进行时与Python自动化出题解析

简介&#xff1a;高二英语寒假作业同步练习资料&#xff0c;聚焦“将来进行时”语法专项&#xff0c;并融合词汇拼写训练&#xff0c;适合高二学生假期自学、备考或教师布置同步作业使用。压缩包内为 1 个 doc 文档&#xff0c;整体仅 56KB&#xff0c;文档结构紧凑&#xff0c…

作者头像 李华
网站建设 2026/9/18 14:39:17

Elasticsearch内存模型调优:堆内堆外、GC与分片瓶颈全解析

看到集群CPU突然飙到90%&#xff0c;Full GC每秒来几次&#xff0c;原本几十毫秒的查询变成好几秒&#xff0c;很多人第一反应就是把堆内存调大——8G改16G&#xff0c;16G改31G&#xff0c;重启完清净一两天&#xff0c;第三天问题又回来了。这种场景我见过太多次。真正的问题…

作者头像 李华
网站建设 2026/9/18 14:37:52

嵌入式Linux SMP移植实战:从设备树到多核启动

简介&#xff1a;这份PDF文献面向嵌入式Linux系统开发人员与内核移植学习者&#xff0c;聚焦多核处理器&#xff08;SMP&#xff09;环境下系统移植的关键技术难题。内容围绕SMP硬件结构、启动流程与设备树机制展开&#xff0c;系统梳理了从硬件分析、设备树构建、内核配置到多…

作者头像 李华