直接写eval脚本难维护因逻辑全挤一行、无法拆分复用、不能注释协作;function load将其变为带元数据的持久化工件,须满足三条件:首行声明、显式注册函数、禁用非常规命令。

为什么直接写EVAL脚本会越来越难维护
因为所有逻辑都挤在一行字符串里,没有函数拆分、不能复用、没法加注释,更别说多人协作。你改一个计数逻辑,得翻遍所有EVAL调用点;上线后发现bug,还得手动SCRIPT FLUSH再重载——而这时主从已切换,脚本早丢了。
用FUNCTION LOAD把脚本变成可管理的库
核心不是“换命令”,而是把脚本组织成带元数据的持久化工件。必须满足三个硬性条件,缺一不可:
-
#!lua name=lib:inventory必须是文件第一行,空格、空行、注释都不行 - 所有函数必须显式注册:
redis.register_function("decr_stock", function(keys, args) ... end) - 不能用
redis.call("INCR")以外的大写命令,REDIS.CALL或redis.Call全报错
加载命令也得带REPLACE:cat inventory.lua | redis-cli -x FUNCTION LOAD REPLACE,否则同名库冲突直接失败。
拆函数比拼大脚本更安全
旧脚本常把“查库存→扣减→写日志→发通知”全塞进一个EVAL,Functions不允许这样。每个函数只做一件事,靠组合调用实现复杂流程:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 用
FCALL stock.check 1 item:123先校验 - 再用
FCALL stock.decr 1 item:123 1执行扣减 - 失败时靠
FCALL_RO查状态,不污染主节点
好处是:单个函数出问题不影响其他功能;测试可针对stock.check单独压测;灰度发布只需替换lib:stock整库,不会出现新旧函数混用。
别忽略KEYS和ARGV的强制约束
Functions要求所有键名必须提前声明,不像EVAL能动态拼接。比如你想根据ARGV[1]构造key:"user:"..ARGV[1]..":profile"——这在Functions里非法,Redis会拒绝执行。
正确做法是客户端把完整key传进来:FCALL user.get 1 user:1001:profile,然后函数里直接用keys[1]。看似多传参数,实则换来两点关键保障:
- 集群模式下路由正确:Redis靠
keys数组决定往哪个分片发请求 - 权限可控:ACL可以限制某函数只能访问
user:*:前缀的key
这个设计看着笨重,但正是它让Functions能真正落地到生产环境——你没法绕过规则去“偷懒”,也就自然规避了大量隐蔽的运维故障。










