欲求不满之 Redis Lua脚本的执行原理

Redis提供了非常丰富的指令集,但是用户依然不满足,希望可以自定义扩充若干指令来完成一些特定领域的问题。Redis 为这样的用户场景提供了 lua脚本支持,用户可以向服务器发送 lua 脚本来执行自…

从对等方接收数据时失败 在上面的示例中,脚本的内容非常短。如果脚本的内容很长并且客户端需要频繁执行,则每次都需要传递冗长的脚本内容,这会浪费网络流量。所以Redis还提供了SCRIPT LOAD和EVALSHA指令来解决这个问题。

SCRIPT LOAD指令用于将客户端提供的lua脚本传递给服务器而不执行,但将获取脚本的唯一ID。此唯一ID是用于唯一标识服务器缓存的lua脚本。 Redis使用它来使用sha1算法。一长串揉捏脚本内容。使用此唯一ID,客户端可以使用EVALSHA命令重复执行脚本。 我们知道Redis有一个incrby指令可以执行整数增量,但不提供诸如自乘的指令。

下面我们使用SCRIPT LOAD和EVALSHA指令来完成平方操作。

首先单行上面的脚本,用分号分隔

加载脚本

命令行输出一个非常长的字符串,这是脚本的唯一标识符。下面我们使用这个唯一标识符来执行指令。

错误处理 上面的脚本参数要求传入的附加参数必须是整数。如果没有传递整数会怎么样?

Failure when receiving data from the peer 从对等方接收数据时失败 看到这里细心的同学会发现两个疑问。第一个是为什么脚本kill命令执行2.58秒,第二个是脚本被卡住,Redis来自空闲kill脚本。如果您尝试在第二个窗口上执行redis-cli以连接到服务器,您还将找到第三个嫌疑人。 Redis-cli建立连接有点慢,大约需要1秒钟。 脚本杀戮的原则 现在我要开始揭示杀人的原则。 lua脚本引擎太强大了。它提供了各种钩子函数,允许在内部虚拟机执行指令时运行钩子代码。例如,每次执行钩子来执行钩子函数时,Redis都使用这个钩子函数。

Redis将忙于处理客户端请求的钩子函数,并且只会在检测到lua脚本执行超时后处理请求。默认超时为5秒。所以上面提出的三个疑点已经消失了。 思考问题 在延迟队列部分,我们使用zrangebyscore和zdel指令来竞争延迟队列中的任务,并且zdel的返回值确定哪个客户端已经抓取任务,这意味着客户端不抓取任务。会有这样一种感觉,即——已到达肉的口(任务)并最终被其他人带走,这将是非常不舒服的。如果你可以使用lua脚本来实现scramble逻辑,那么zrangebyscore和zdel指令就会被原子化地执行。读者可以尝试一下。