function load 必须加 replace 才能覆盖同名库,否则报错 err library already exists;首行须为#!lua name=xxx且无空行,命令名全小写,禁用非安全模块,fcall 要求 keys 同 slot。

FUNCTION LOAD 必须加 REPLACE 才能覆盖旧库
集群里反复加载同名函数库却不加 REPLACE,会直接报错 ERR Library already exists。这不是权限或连接问题,是 Redis 的强制校验——函数库名(如 name=stats)全局唯一,不允许静默覆盖。
- 每次部署新版本函数,命令必须带
REPLACE:cat mylib.lua | redis-cli -x FUNCTION LOAD REPLACE -
-x是关键:它让redis-cli把整个 stdin 当作单个参数传给FUNCTION LOAD,避免 shell 把换行或空格截断 - 不加
REPLACE时,哪怕只改了一行逻辑,加载也会失败;加了则自动丢弃旧版本、注册新版本
函数文件第一行必须是 #!lua name=xxx,且不能有空行
把老 EVAL 脚本内容直接塞进 FUNCTION LOAD,90% 会卡在解析阶段,典型报错是 user_script:1: unexpected symbol 或 attempt to call a nil value (global 'redis')。根本原因不是语法错,而是 Functions 的沙箱启动协议没满足。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 第一行且仅第一行,必须是
#!lua name=mylib(可选加version=1),后面紧接换行,不能有空行、注释或 BOM - 所有
redis.call()命令名必须小写:redis.call("incr", key)合法,redis.CALL("INCR", key)直接报错 - 删掉
os.time()、io.open()、loadstring()—— 这些模块在 Functions 环境里根本不存在
FCALL 在集群中自动路由,但 keys 参数必须严格对齐 slot
别指望 FCALL mylib.myfunc 2 user:1001 order:2026 能跨 slot 执行。Redis 不会帮你拆解 key 的哈希槽,它只按第一个 key 的 slot 路由到对应节点——如果其他 key 不在同一个 slot,调用直接失败,报错 ERR Cluster key hash slot not covered。
- 确保所有传入
keys数组的 key 都属于同一哈希槽,最稳妥的是用相同前缀 + hash tag,比如user:{1001}:profile和user:{1001}:settings - 不要在函数里调用
KEYS *或SCAN—— 这类命令在集群模式下被禁用,且严重阻塞主线程 - 如果业务确实需要多 slot 操作,得由客户端分片调用,函数内部只处理单 slot 数据
FUNCTION LIST 和 FUNCTION STATS 是上线前必查项
很多故障不是函数写错了,而是压根没加载成功,或者加载到了错误节点。别依赖“我刚刚跑了命令”这种直觉,集群里每个节点都得单独验证。
- 在每个主节点上运行
FUNCTION LIST | grep -A 5 mylib,确认library_name、engine和functions数量一致 - 执行
FUNCTION STATS查看num_fails和total_calls,刚上线时错误率 > 0 很常见,但持续为 0 说明函数根本没被调用过 - 调用失败时,错误信息比
EVAL清晰得多:比如ERR Unknown function: mylib.mysum就说明FUNCTION LIST里没这名字,而不是脚本语法问题
#!lua name=xxx 后面多一个空行,整个函数就废了。










