redis 7.0的function并非执行更快,而是通过持久化、自动复制和全局注册避免fallback重传,显著降低网络带宽波动(实测降60%+)和集群调用失败率,并减少每次调用的解析开销。

Redis 7.0 的 FUNCTION 并不比旧版 EVAL/EVALSHA 更快——它在单次执行耗时、CPU 占用、Lua 解释开销上几乎一致,因为底层仍是同一个 Lua 5.1 解释器。所谓“性能优势”其实是**可靠性带来的间接性能收益**:避免因脚本丢失导致的 fallback 到完整脚本传输、重试、超时中断等真实损耗。
FUNCTION LOAD 后 FCALL 不再触发网络带宽放大
旧版 SCRIPT LOAD + EVALSHA 看似省流量,但一旦主节点重启或从节点重连,EVALSHA 立即报错 ERR NOSCRIPT No matching script,客户端必须 fallback 到 EVAL 发送完整脚本(可能几百字节甚至 KB 级)。集群中某分片节点漏加载,也会触发同样 fallback。
-
FUNCTION LOAD注册的函数写入 AOF/RDB,重启后自动恢复,FCALL始终走轻量协议,无 fallback 风险 - 实测在频繁主从切换或滚动重启场景下,网络带宽波动可降低 60%+(尤其当脚本体较大、调用频次高时)
- 注意:
FCALL仍需序列化函数名、key 数量、keys/args 数组,但不传 Lua 源码 —— 这是唯一确定的带宽节省点
集群模式下调用失败率大幅下降
Redis 6.x 集群中,SCRIPT LOAD 是 per-node 操作;7.x 对 EVALSHA 做了更严格校验,未预加载的节点直接返回 NOSCRIPT,不再静默 fallback。
- 旧方案需在部署阶段对所有分片节点逐个执行
SCRIPT LOAD,漏一个就出问题;扩缩容后新节点默认无脚本 -
FUNCTION库名全局注册,FCALL自动路由到数据所在节点,且函数定义已通过复制协议同步到位 - 无需客户端维护节点级脚本状态,也无需在请求链路中插入
SCRIPT LOAD重试逻辑
函数元信息缓存与调用开销几乎为零
FUNCTION 的解析和注册发生在 FUNCTION LOAD 阶段,之后 FCALL 不再做语法检查、沙箱初始化或权限验证(只要函数存在且未被 FUNCTION KILL);而 EVAL 每次都要做完整校验:
-
EVAL:校验 Lua 语法 → 编译字节码 → 沙箱初始化 → 执行 → 清理(首次还额外计算 SHA1) -
FCALL:查函数表 → 绑定 keys/args → 执行已编译函数体 → 返回(跳过全部前端解析) - 实际压测显示,在 warmup 充分前提下,
FCALL比EVALSHA快 3%~8%,但比EVAL快 20%+(后者每次都要编译)
真正容易被忽略的是:这些“优势”只在脚本长期存活、跨节点复用、集群规模大于 3 节点时才明显。如果只是单机 Redis + 简单限流脚本,EVALSHA 和 FCALL 的 RT 差异几乎不可测——但故障率、运维负担、灰度难度的差距,会随着系统生命周期指数级放大。











