Redis Functions 怎样加载可重复调用的服务端函数
来源:17golang原创
时间:2026-10-29 00:21:08 325浏览 收藏
如果一段 Lua 逻辑需要被多个请求反复调用,Redis Functions 的做法是先把“库”加载到 Redis,再用函数名调用,而不是每次把完整脚本重新发过去。最小闭环只有三件事:源码以 #!lua name=库名 开头,库内通过 redis.register_function 注册入口,加载后用 FCALL 函数名 numkeys ... 调用。
官方地址:https://redis.io/docs/latest/develop/programmability/functions-intro/
本文只围绕“怎样加载并重复调用一个服务端函数”展开。下面的命令和输出是用于说明语义的示例,不代表在本文环境中实际运行过。
先判断:应该加载库,还是每次发送脚本
Redis 7 引入的 Functions 把函数作为数据库管理的服务端工件。相比每次用 EVAL 发送脚本,调用方只依赖函数 API;库可以包含多个函数,库名和函数名也比一串 SHA 更容易在排查时识别。
| 方式 | 代码在哪里 | 适合的调用形态 |
|---|---|---|
| EVAL | 客户端请求里 | 临时执行一次脚本 |
| EVALSHA | Redis 脚本缓存里 | 客户端维护脚本并重复调用 |
| Redis Functions | Redis 的函数库里 | 先部署库,再由多个调用方按函数名重复使用 |
选择 Functions 后,第一步不是直接写 FCALL,而是先准备一个可加载的 library。空库会失败,因为 Redis 要求库至少注册一个函数。
一份能加载的最小 Lua 库
下面的库名是 orderlib,函数名是 mark_order。它接收一个订单 key 和一组普通参数,把状态写入 Hash。示例特意把 key 与普通参数分开,后面调用 FCALL 时就能看出 numkeys 的作用。
#!lua name=orderlib
-- 注册一个需要一个 Redis key 的服务端函数。
local function mark_order(keys, args)
-- keys[1] 必须来自 FCALL 的 key 区域,不能把它当普通参数传入。
if #keys ~= 1 then
return redis.error_reply('mark_order requires exactly one key')
end
-- 普通参数按顺序放在 args 中:字段名和值各占一个位置。
if #args ~= 2 then
return redis.error_reply('mark_order requires field and value')
end
return redis.call('HSET', keys[1], args[1], args[2])
end
-- 只有注册后的名字才能通过 FCALL 找到这个函数。
redis.register_function('mark_order', mark_order)
其中 Shebang 的 name=orderlib 是库名,不是函数名;mark_order 才是之后传给 FCALL 的入口名。一个库可以注册多个函数,但它们会随库一起加载和更新。

用 FUNCTION LOAD 首次加载,用 REPLACE 整库更新
Redis 的命令语法是 FUNCTION LOAD [REPLACE] function-code。如果源码保存为 orderlib.lua,可以把整个文件通过标准输入交给 redis-cli -x:
# 首次把完整 Lua 库交给 Redis;-x 让 redis-cli 从标准输入读取库源码。 cat orderlib.lua | redis-cli -x FUNCTION LOAD # 修改库内任意函数后,使用 REPLACE 以整库为单位替换旧定义。 cat orderlib.lua | redis-cli -x FUNCTION LOAD REPLACE
首次加载成功时,返回值是库名 orderlib。如果同名库已经存在而没有写 REPLACE,Redis 会拒绝本次加载;REPLACE 不是只替换一个函数,而是用新的完整库定义覆盖旧库,所以发布时应把库内所有函数一起纳入版本管理。
orderlib
(error) ERR Library 'orderlib' already exists
orderlib
不要把返回的库名误当成函数调用名。加载成功只是说明库被接受,真正调用仍要传入已注册的函数名。
用 FCALL 调用:numkeys 决定参数分区
这个例子里函数只需要一个 key,因此 numkeys 写成 1:
# 1 表示后面的第一个参数是 key;其余两个参数是普通参数。 redis-cli FCALL mark_order 1 order:100 status paid # 读取刚才由函数写入的字段,用于理解返回值语义。 redis-cli HGET order:100 status
(integer) 1
paid
Redis 会把 order:100 放进 Lua 回调的 keys 表,把 status 和 paid 放进 args 表。如果把 numkeys 写成 0,函数内部的 keys 就为空;如果写成 2,第二个参数也会被当成 key。这个数字不是“参数总数”,而是 key 参数的数量。
在 Redis Cluster 中,函数访问的所有 key 都必须显式出现在 key 区域,并且同一次调用的 key 要满足集群的路由约束。不要把 key 拼在普通参数里来绕过这个边界。

加载完成后怎样判断没有走错
可以按“库—函数—调用参数”三个层次判断。先用 FUNCTION LIST 查看库名和已注册函数,再用一次最小 FCALL 检查函数名与 key 数量是否一致:
# 列出服务端已加载的库和函数元数据。 redis-cli FUNCTION LIST # 本例的 mark_order 会写 Hash,所以使用普通 FCALL。 redis-cli FCALL mark_order 1 order:100 status shipped
排查时重点看这几类结果:
- 返回
ERR No functions registered:库源码只有 Shebang,没有调用redis.register_function。 - 返回“库已存在”:首次加载命令重复执行,确认是否应该使用
REPLACE。 - 函数报 key 数量错误:检查
FCALL的numkeys,不要先改 Lua 逻辑。 - 集群只有部分节点能找到函数:Redis Cluster 需要由管理员把库加载到所有 master 节点;副本传播不等于集群所有 master 自动完成部署。
Redis Functions 的执行仍然是原子的,并会在执行期间阻塞服务器处理其他活动,因此函数应保持短小,不能把长时间计算或等待外部资源的工作塞进一次函数调用。
常见问题
FUNCTION LOAD 返回的是函数名吗?
不是。成功返回加载的库名;函数名来自 redis.register_function,之后由 FCALL 使用。
修改一个函数时能否只上传这个函数?
不能把库当成可选择更新的函数集合。Redis Functions 以库为更新单位,使用 FUNCTION LOAD REPLACE 时应提交包含全部注册函数的完整库源码。
总结一下:先用带 Shebang 的 Lua 源码注册函数,再用 FUNCTION LOAD 首次加载、用 REPLACE 更新整库,最后通过正确的 numkeys 把 key 与普通参数分开传给 FCALL。这样库的部署动作和业务调用动作就能清晰分离。
-
117 收藏
-
426 收藏
-
171 收藏
-
113 收藏
-
195 收藏
-
397 收藏
-
342 收藏
-
331 收藏
-
348 收藏
-
275 收藏
-
168 收藏
-
371 收藏
-
154 收藏
-
468 收藏
-
176 收藏
-
338 收藏
-
238 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习