首页 / Redis 入门教程 / 24. 函数 FUNCTION 与 ACL

Redis 入门教程

24. 函数 FUNCTION 与 ACL

本教程共 40 篇 · 第 24 篇 · 更新于 2026-08-02

FUNCTIONFCALL函数ACL访问控制用户权限

24. 函数 FUNCTION 与 ACL

第 23 章讲了用 EVAL 运行 Lua 脚本。它足够好,但有个治理痛点:脚本源码散落在各个应用实例里,每个实例都得自己持有脚本、自己处理缓存与降级,难以统一管理和版本化。从 Redis 7.0 起,Redis 给出了更好的方案——函数(Function):把脚本变成数据库的“一等公民”,先加载进库、再被所有客户端调用。

另一方面,Redis 暴露在公网或多人共用时,不能让任何人执行任何命令。Redis 6 引入、并在 8.x 持续完善的 ACL(Access Control List,访问控制列表),让你可以创建多个带精细权限的用户。本章把这两项“服务端治理 + 安全防护”的能力一并讲清。

本节目标

  • 理解函数(FUNCTION)相比 EVAL 脚本的优势:成为数据库一等公民、集中管理。
  • 掌握 FUNCTION LOAD 加载、FCALL 调用、FUNCTION LIST / FUNCTION DELETE 管理。
  • 理解 ACL 的由来:取代单一的 requirepass,支持多用户与细粒度授权。
  • ACL SETUSER 创建用户,配置命令权限(+@cat)、键范围(~pattern)、频道(&pattern)与密码。
  • 知道生产环境 ACL 的基本安全建议。

函数 FUNCTION

函数的本质是“加载进 Redis 的命名脚本”。它一经 FUNCTION LOAD 加载,就常驻数据库,所有连接的客户端都能用 FCALL 按名字调用,应用层不再需要持有源码、也不再依赖 EVALSHA 的缓存降级逻辑。

加载一个函数(用 FUNCTION LOAD,Lua 函数需声明 redis.register_function):

127.0.0.1:6379> FUNCTION LOAD "#!lua name=mylib\nredis.register_function('incrby', function(keys, args) return redis.call('INCRBY', keys[1], args[1]) end)"
"mylib"

上面把名为 mylib 的库加载进来,其中注册了一个函数 incrby。随后用 FCALL 调用,参数同样是 函数名 numkeys KEYS... ARGV...

127.0.0.1:6379> FCALL incrby 1 mycounter 5
(integer) 5
127.0.0.1:6379> FCALL incrby 1 mycounter 5
(integer) 10

常用管理命令:

  • FUNCTION LIST:列出已加载的函数库。
  • FUNCTION INFO libname:查看某个库的详情。
  • FUNCTION DELETE libname:删除函数库(注意会移除其中所有函数)。
  • FUNCTION FLUSH:清空全部函数(支持 ASYNC / SYNC)。
  • FUNCTION KILL:终止正在运行的只读函数(类比 SCRIPT KILL)。

函数与脚本一样是原子执行、阻塞全服的,第 23 章关于“不要写慢脚本、留意 busy-reply-threshold”的全部建议,对函数同样适用。只读函数也可用 FCALL_RO 调用,获得在从节点运行、可随时 FUNCTION KILL 等好处。

提示:FUNCTION 是 Redis 7.0 引入的能力,在 Redis 8.x 中已是推荐的服务端编程方式。当你需要在多个应用、多语言客户端间共享同一段服务端逻辑时,优先用 FUNCTION 而非各自 EVAL,可避免“脚本散落、版本不一致”的运维灾难。需要向下兼容老版本集群时,才退回 EVAL。

ACL:多用户与精细授权

在 Redis 6 之前,访问控制只有一个 requirepass——所有连上的人用同一个密码、拥有全部权限。这显然不适合多团队共用或对外暴露的实例。ACL 让 Redis 支持多个用户,每个用户可以被精确限制“能执行哪些命令、能碰哪些 key、能访问哪些频道”。

Redis 默认存在一个 default 用户。新连接若以 defaultnopass 登录,就拥有全部权限(这也是很多开发环境“裸奔”的原因)。用 AUTH 以特定用户登录:

127.0.0.1:6379> ACL WHOAMI
"default"

创建受限用户

ACL SETUSER 创建用户。规则语法(与 redis.confuser 指令一致):

  • on / off:启用 / 禁用该用户;
  • >password:设置密码(<password 删除,nopass 表示免密);
  • +<cmd> / -<cmd>:允许 / 禁止某命令,+@<category> 允许某类命令;
  • ~<pattern>:允许访问的 key 模式(~* 表示所有);
  • &<pattern>:允许访问的 Pub/Sub 频道模式。

下面创建一个只能操作 list 类命令、且只能碰 jobs:* 这个 key 前缀、免密的用户 worker

127.0.0.1:6379> ACL SETUSER worker on nopass +@list +@connection ~jobs:* &
OK

用该用户登录后,只能对 jobs: 开头的 key 用 list 命令:

127.0.0.1:6379> AUTH worker ""
OK
127.0.0.1:6379> RPUSH jobs:queue task1
(integer) 1
127.0.0.1:6379> GET jobs:queue
(error) NOSCRIPT ... WRONGTYPE ... (error) ACL denied ...

(最后一行被拒绝,因为 worker 没有 +@stringGET 权限,且 ~jobs:* 之外的 key 也被禁止。)

命令类别与最小权限

@list@string@set@sortedset 等是命令类别,可用 +@类别 批量授权。特殊类别有:

  • @all:所有命令(allcommands 是其别名)。
  • @admin:管理类高危命令(如 FLUSHALLCONFIGSHUTDOWNACL)。
  • @dangerous:危险命令集合。

生产上遵循最小权限原则:给应用账号只开它真正需要的类别,并尽量用 ~appname:* 限制 key 前缀,避免它误删别人的数据。

其他 ACL 命令:

  • ACL LIST:列出所有用户及其规则。
  • ACL GETUSER name:查看某用户详情。
  • ACL WHOAMI:当前连接所用用户。
  • ACL DELUSER name:删除用户。
  • ACL LOG:查看因 ACL 被拒绝的命令记录,便于排查。

提示:用 aclfile 配置项可把 ACL 规则写到独立文件,由 ACL LOAD 加载;这与 requirepass 互斥。生产环境推荐用外部 ACL 文件管理用户,而不是把规则写死在 redis.conf 里,便于集中运维与版本控制。注意 default 用户若设了密码,新连接就必须 AUTH,这正是“关掉裸奔”的关键一步。

安全小建议

  • 永远给 default 用户设密码,或干脆禁用它(ACL SETUSER default off)。
  • 应用使用专用低权限用户,按业务划分 key 前缀与命令类别。
  • 配合 protected-mode yes 与绑定内网地址,不要把 Redis 裸暴露到公网。
  • 高危命令可用 ACL 重命名或禁用(如把 FLUSHALL 仅对管理员开放)。

小结

  • 函数 FUNCTION 是 Redis 7+ 推荐的服务端编程方式:用 FUNCTION LOAD 加载、FCALL 调用,逻辑常驻数据库、集中管理,优于散落的 EVAL。
  • 函数同样原子、阻塞全服,请遵循“短脚本”原则;只读函数用 FCALL_RO
  • ACL 取代了单一 requirepass,支持多用户与最小权限:命令(+@cat)、key(~pattern)、频道(&pattern)、密码(>pw)四个维度。
  • ACL SETUSER 建用户、ACL LIST / ACL LOG 排查;生产用外部 aclfile 管理。
  • 安全底线:关掉 default 裸奔、应用用低权限专用账号、不裸暴露公网。

常见误区

  • 误区一:把 FUNCTION 当成“更好的 EVAL”就随便用。 函数的优势是“常驻数据库、集中管理”,但它和脚本一样原子且阻塞全服。如果函数逻辑写得很长、遍历超大集合,危害与慢脚本完全相同——会卡住整个实例。务必保持函数短小。
  • 误区二:以为 ACL 只是“多设几个密码”。 ACL 的精髓是最小权限:用 +@类别 限定命令、~pattern 限定 key 前缀、&pattern 限定频道。给应用开一个“只能碰自己业务 key、只有需要的命令类别”的专用账号,远比共享一个全权限账号安全。
  • 误区三:忘了关掉 default 用户的“裸奔”。 默认 default 用户常是 nopass 且拥有全部权限,任何人连上就能为所欲为。生产环境应给 default 设密码或干脆 ACL SETUSER default off,再为应用创建受限用户。
  • 误区四:把 requirepassaclfile 混用。 二者互斥:一旦用外部 ACL 文件(aclfile),就不能再用单密码模式。迁移到 ACL 体系时,记得把旧 requirepass 逻辑迁进用户规则里,否则启动会报错。

提示:本教程统一基于 Redis 8.x(最新稳定版)行文。补充说明:官方 redis.io 下载页另标 8.8 为 “Latest stable”,而 GitHub 上的最新发布 tag 为 8.10.0,二者同属 8.x 大版本,对 FUNCTION 与 ACL 命令及语义的讲述没有影响。