Redis提供了多种调试Lua脚本的有效方法:1)使用redis.log输出详细日志;2)分步执行EVAL命令测试;3)使用table序列化输出复杂数据;4)添加错误处理机制;5)构建完整调试框架;6)利用外部测试工具。调试时建议启用Redis日志、使用有意义的调试信息、逐步构建脚本,并注意生产环境关闭调试以避免性能影响。这些方法可帮助开发者有效排查Lua脚本中的问题。
在 Redis 中调试 Lua 脚本确实比较困难,但有以下几种有效的方法:
方法 1:使用 Redis 日志输出调试(最常用)
基本日志输出
Lua
-- 在 Lua 脚本中添加日志输出
redis.log(redis.LOG_NOTICE, "DEBUG: 变量值 = " .. tostring(my_var))
redis.log(redis.LOG_NOTICE, "DEBUG: 进入函数 X")
完整示例
Lua
local function process_data(key)
redis.log(redis.LOG_NOTICE, "DEBUG: 开始处理键 " .. key)
local value = redis.call('GET', key)
redis.log(redis.LOG_NOTICE, "DEBUG: 获取的值 = " .. tostring(value))
-- 业务逻辑
if value then
redis.log(redis.LOG_NOTICE, "DEBUG: 值存在,进行处理")
return redis.call('INCR', key)
else
redis.log(redis.LOG_NOTICE, "DEBUG: 值不存在")
return nil
end
end
-- 主程序
redis.log(redis.LOG_NOTICE, "DEBUG: 脚本开始执行")
local result = process_data(KEYS[1])
redis.log(redis.LOG_NOTICE, "DEBUG: 最终结果 = " .. tostring(result))
return result
查看 Redis 日志
bash
# 查看 Redis 日志(需要先在 redis.conf 中启用日志)
tail -f /var/log/redis/redis-server.log
# 或者实时监控日志
redis-cli monitor
实践过程
环境
php7.4 + redis 6.2.8(docker)
lua代码: (结合目前项目环境做了调整)
Lua
require "Header.lua"
return main(function(params)
local function process_data(key)
redis.log(redis.LOG_NOTICE, "DEBUG: 开始处理键 " .. key)
local value = redis.call('GET', key)
redis.log(redis.LOG_NOTICE, "DEBUG: 获取的值 = " .. tostring(value))
-- 业务逻辑
if value then
redis.log(redis.LOG_NOTICE, "DEBUG: 值存在,进行处理")
return redis.call('INCR', key)
else
redis.log(redis.LOG_NOTICE, "DEBUG: 值不存在")
return nil
end
end
-- 主程序
redis.log(redis.LOG_NOTICE, "DEBUG: 脚本开始执行")
local result = process_data(params.hello)
redis.log(redis.LOG_NOTICE, "DEBUG: 最终结果 = " .. tostring(result))
return result
end)
PHP代码:
Lua
public function test_60(){
$ret = LuaBuilder::exec("test", 4, ["hello" => "world"]);
dd($ret);
}
执行PHP输出:

查看日志:

方法 2:使用 Redis EVAL 命令逐步测试
分步执行测试
bash
# 第一步:测试简单命令
redis-cli eval "return 'Hello World'" 0
# 第二步:测试带参数的脚本
redis-cli eval "return ARGV[1]" 0 "test_param"
# 第三步:测试 Redis 命令
redis-cli eval "return redis.call('GET', KEYS[1])" 1 mykey
# 第四步:组合完整逻辑
方法 3:使用 Lua 的 table 序列化输出复杂数据
local function dump_table(tbl, indent)
if not indent then indent = 0 end
for k, v in pairs(tbl) do
local formatting = string.rep(" ", indent) .. k .. ": "
if type(v) == "table" then
redis.log(redis.LOG_NOTICE, "DEBUG: " .. formatting)
dump_table(v, indent + 1)
else
redis.log(redis.LOG_NOTICE, "DEBUG: " .. formatting .. tostring(v))
end
end
end
-- 使用示例
local my_table = {a = 1, b = {c = 2, d = 3}}
dump_table(my_table)
方法 4:错误处理和调试信息
Lua
local function safe_redis_call(command, ...)
local success, result = pcall(redis.call, command, ...)
if not success then
redis.log(redis.LOG_NOTICE, "DEBUG: Redis 命令失败: " .. command .. " - " .. result)
return nil
end
return result
end
-- 使用安全的调用方式
local value = safe_redis_call('GET', KEYS[1])
方法 5:完整的调试框架
Lua
-- 调试工具函数
local Debug = {
enabled = true,
level = "NOTICE"
}
function Debug:log(message, data)
if self.enabled then
local log_msg = "DEBUG: " .. message
if data then
log_msg = log_msg .. " | Data: " .. tostring(data)
end
redis.log(redis.LOG_NOTICE, log_msg)
end
end
function Debug:start_section(name)
self:log("=== 开始: " .. name .. " ===")
end
function Debug:end_section(name)
self:log("=== 结束: " .. name .. " ===")
end
-- 使用调试框架
Debug:start_section("用户处理")
Debug:log("用户ID", ARGV[1])
local user_data = redis.call('HGETALL', 'user:' .. ARGV[1])
Debug:log("用户数据", #user_data / 2 .. " 个字段")
Debug:end_section("用户处理")
方法 6:外部调试技巧
在本地测试 Lua 脚本
Lua
-- 创建测试环境
local redis = {
call = function(cmd, ...)
print("Redis call:", cmd, ...)
return "mock_response"
end,
LOG_NOTICE = "notice"
}
-- 模拟 redis.log
function redis.log(level, message)
print("LOG["..level.."]:", message)
end
-- 在这里粘贴你的 Redis Lua 脚本进行测试
使用 Redis Insight 或可视化工具
- RedisInsight: Redis 官方可视化工具,可以执行和调试脚本
- rdb: 命令行工具,支持更好的输出格式
调试最佳实践
- 启用 Redis 日志
bash
# redis.conf
loglevel notice
logfile /var/log/redis/redis.log
- 使用有意义的调试信息
Lua
-- 不好的调试
redis.log(redis.LOG_NOTICE, "value: " .. value)
-- 好的调试
redis.log(redis.LOG_NOTICE, "DEBUG[用户积分]: 用户 " .. user_id .. " 的积分为: " .. points)
- 逐步构建脚本
Lua
-- 先测试小片段,再组合成完整脚本
注意事项
- Redis Lua 脚本是原子执行的,无法真正"单步调试"
- 大量日志可能影响性能,生产环境记得关闭调试
- 复杂调试建议在测试环境进行
选择最适合你需求的方法进行调试!
最后: 还有一个更加简单的办法
直接调用 redis.set("hello", "world")
Lua
local function zsetJson(key,value)
if __log_zset then
local str = encodeJson(value)
if string.len(str) > 100 then
log({"zsetJson",key,string.sub(str,0,100)})
else
log({"zsetJson",key,value})
end
end
redis.call("set",key,encodeJson(value))
end
注: 只要能帮助开发, 提高效率就是好的方式;