如何确定 Redis 中 Lua 脚本的执行时间?

3
我有一个小的Lua脚本要在Redis中运行,我想知道执行时间。 由于Redis和它的Lua实现的特性,我无法在脚本的开始/返回点使用TIME函数,并将此信息包含在返回结果中进行处理(参见http://redis.io/commands/eval-作为纯函数的脚本)。这会导致错误:(error) ERR Error running script (call to f_a49ed2fea72f1f529843d6024d1515e76e69bcbd): Write commands not allowed after non deterministic commands 我已经搜索了一些函数/调用,可以返回最后一次运行脚本的执行时间,但是还没有找到合适的。 我正在使用PHP和Predis库。虽然我可以从PHP端检查执行时间,但我希望消除传输开销并找出Lua脚本将阻止对数据库访问的时间。如果我不需要更改Redis中存储的任何数据,则可以成功返回时间,并且这些时间约为PHP报告的时间的1/10。 如何确定Redis中Lua脚本的执行时间,而不是通过PHP?

大多数实现都有os.clock()函数,它返回自执行开始以来经过的时间量。 - Darkwater
我刚刚尝试在一个脚本中调用 os.clock(),但是返回了一个错误,指出“脚本尝试访问不存在的全局变量 'os'”。看起来这个变量不可用。无论如何,谢谢! - Pete C
1
@PeteC LUA中的redis库中没有OS库,请参考https://dev59.com/zF0Z5IYBdhLWcg3wdQEy#31433599。 - Bharat Pahalwani
4个回答

5
您可以通过将slowlog-log-slower-than参数更改为0来激活Redis慢日志功能。它将记录所有命令(包括Lua脚本和执行时间)的执行时间。
慢日志保存在内存队列中,您需要定期转储以收集数据。根据流量的大小,您可能需要增加slowlog-max-len以确保捕获您感兴趣的执行时间。
您可以使用slowlog get command命令转储慢日志。由您过滤不需要的结果。据我所知,在数据收集时没有过滤Lua统计信息的可能性。

2

如果您在构建Redis时启用了os模块,可以在脚本中使用os.clock()。

请在https://github.com/antirez/redis/blob/unstable/src/scripting.c的第484行将#if 0更改为#if 1

void luaLoadLibraries(lua_State *lua) {
    luaLoadLib(lua, "", luaopen_base);
    luaLoadLib(lua, LUA_TABLIBNAME, luaopen_table);
    luaLoadLib(lua, LUA_STRLIBNAME, luaopen_string);
    luaLoadLib(lua, LUA_MATHLIBNAME, luaopen_math);
    luaLoadLib(lua, LUA_DBLIBNAME, luaopen_debug); 
    luaLoadLib(lua, "cjson", luaopen_cjson);
    luaLoadLib(lua, "struct", luaopen_struct);
    luaLoadLib(lua, "cmsgpack", luaopen_cmsgpack);

#if 0 /* Stuff that we don't load currently, for sandboxing concerns. */
    luaLoadLib(lua, LUA_LOADLIBNAME, luaopen_package);
    luaLoadLib(lua, LUA_OSLIBNAME, luaopen_os);
#endif
}

0
从Redis v3.2开始,您可以通过调用新的redis.replicate_commands() API来选择复制命令而不是脚本。这将使您能够在执行写操作的脚本中调用TIME等操作,而不会触发不确定性错误。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接