201025-Redis之Lua脚本调试

Redis之Lua脚本调试

Redis Lua调试器,代号LDB,具有以下重要功能:

  • 它使用服务器 - 客户端模型,因此它是一个远程调试器。Redis服务器充当调试服务器,而默认客户端则是redis-cli。但是,可以通过遵循服务器实现的简单协议来开发其他客户端。
  • 默认情况下,每个新的调试会话都是分叉会话。这意味着在调试Redis Lua脚本时,服务器不会阻塞并可用于开发或者为了并行执行多个调试会话。这也意味着在脚本调试会话结束后回滚更改,因此可以使用与上一个调试会话完全相同的Redis数据集再次重新启动新的调试会话。
  • 可以根据需要使用备用同步(非分叉)调试模型,以便可以保留对数据集的更改。在此模式下,服务器会阻止调试会话处于活动状态。
  • 支持逐步执行。
  • 支持静态和动态断点。
  • 支持将调试脚本记录到调试器控制台中。
  • 检查Lua变量。
  • 跟踪由脚本执行的Redis命令。
  • Redis和Lua值的漂亮印刷。
  • 无限循环和长执行检测,模拟断点。

重要说明:请确保使用Redis生产服务器避免调试Lua脚本。请改用开发服务器。另请注意,使用同步调试模式(这不是默认设置)会导致Redis服务器阻塞调试会话持续的所有时间。

rollback

调试步骤

要使用redis-cli以下步骤启动新的调试会话:

  1. 使用编辑器(ZeroBrane Studio)在某个文件中创建脚本。假设您正在编辑位于的Redis Lua脚本 /tmp/script.lua
  2. 启动调试会话:
1
redis-cli -a hc --ldb --eval script.lua mykey key , 0 10000 jdi 3021081616280006280431

请注意,通过–eval选项,redis-cli您可以将键名和参数传递给脚本,并以逗号分隔。
3. 进入一个redis-cli不再接受其正常命令的特殊模式,而是打印一个帮助屏幕并将未修改的调试命令直接传递给Redis。
debug模式
4. 启动调试器时,它将以步进模式启动。它将停止在脚本的第一行,它在执行之前实际执行某些操作。
5. 从这一点开始,您通常会调用step以执行该行并转到下一行。在您执行步骤时,Redis将显示服务器执行的所有命令,如以下示例所示:
step
<redis><reply>线示出通过仅执行的行执行的命令,以及来自服务器的答复。

1
2
<redis> scan 0 count 10000 match jdi*
<reply> ["0",["jdi-118690f13f50495caae5c48c77711b03","jdi-d764a3827fec4df1878567c98bfa15b2","jdi-fbd75d8b634c4cecbd213916682fa07d","jdi-d8d6a99ddfd545b38a94daf3d31a7f37","jdi-0791650ac8444a27bd7b43f8d5620c77","jdi-ce40fe22e90e491a90e1a69e90535bc1","jdi-7c8 .

请注意,这仅在步进模式下发生。如果您使用continue以执行脚本直到下一个断点,则不会将命令转储到屏幕上以防止输出过多

stepmore

stepcontinue

终止调试会话

  1. 当脚本自然终止时,调试会话结束,redis-cli以正常的非调试模式返回。您可以像往常一样使用该restart命令重新启动会话。
  2. redis-cli 通过按下手动中断Ctrl+C。请注意,也无论如何打破之间的连接redis-cli和redis-server将中断调试会话。
  3. 关闭服务器时,所有分叉的调试会话都将终止。

缩写调试命令

调试可能是一个非常重复的任务。因此,每个Redis调试器命令都以不同的字符开头,您可以使用单个初始字符来引用该命令。

因此,例如,step您可以输入而不是键入s。

断点

如在线帮助中所述,添加和删除断点很简单。只需使用b 1 2 3 4在第1,2,3,4行添加b 0断点。该命令将删除所有断点。可以使用as参数删除选定的断点,即我们要删除的断点所在的行,但前缀为减号。例如b -3,从第3行中删除断点。

请注意,将断点添加到Lua从不执行的行(如声明局部变量或注释)将不起作用。断点将被添加,但由于脚本的这部分将永远不会被执行,程序将永远不会停止。

断点

动态断点

使用该breakpoint命令可以将断点添加到特定行中。但是,有时我们只想在发生特殊情况时才停止执行程序。为此,您可以使用redis.breakpoint()Lua脚本中的 函数。调用时,它会模拟下一行中将要执行的断点。

if counter > 10 then redis.breakpoint() end
此功能在调试时非常有用,因此我们可以避免多次手动继续执行脚本,直到遇到给定条件。

同步模式

默认LDB使用分叉会话来回滚脚本在调试时所操作的所有数据更改。在调试期间,确定性通常是一件好事,因此可以启动连续的调试会话,而无需将数据库内容重置为其原始状态

但是,为了跟踪某些错误,您可能希望保留每个调试会话对密钥空间执行的更改。当这是一个好主意,你应该使用一个特殊的选项,启动调试器ldb-sync-mode中redis-cli。

1
./redis-cli --ldb-sync-mode --eval /tmp/script.lua

脚本记录

该redis.debug()命令是一个功能强大的调试工具,可以在Redis Lua脚本中调用,以便将内容记录到调试控制台中:

如果脚本在调试会话之外执行,redis.debug()则根本不起作用。请注意,该函数接受多个参数,这些参数由输出中的逗号和空格分隔。

正确显示表和嵌套表,以便为程序员调试脚本使值易于观察。

redisdebug

使用print和检查程序状态eval

虽然redis.debug()可以使用该函数直接从Lua脚本中打印值,但通常在步进或停止到断点时观察程序的局部变量很有用。

该print命令就是这样,并在调用帧中执行查找,从当前的一个回到之前的一个,直到顶层。这意味着即使我们进入Lua脚本中的嵌套函数,我们仍然可以使用print foo查看foo调用函数的上下文中的值。在没有变量名称的情况下调用时,print将打印所有变量及其各自的值。

该eval命令在当前调用帧的上下文之外执行小块Lua脚本(使用当前Lua内部结构无法在当前调用帧的上下文中进行评估)。但是,您可以使用此命令来测试Lua函数。

1
lua debugger> eval redis.call('get','laosan')

eval

printAndeval

调试客户端

LDB使用客户端 - 服务器模型,其中Redis服务器充当使用RESP进行通信的调试服务器。虽然redis-cli是默认的调试客户端,但只要满足以下条件之一,任何客户端都可用于调试:

  1. 客户端提供本机接口,用于设置调试模式和控制调试会话。
  2. 客户端提供了一个通过RESP发送任意命令的接口。
  3. 客户端允许将原始消息发送到Redis服务器。

参考资料

Redis Lua scripts debugger

# ,
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×