在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Redis提供了Lua脚本功能来让用户实现自己的原子命令,但也存在着风险,编写不当的脚本可能阻塞线程导致整个Redis服务不可用。 本文将介绍Redis中Lua脚本的基本用法,以及脚本超时导致的问题和处理方式。 EVAL命令简介eval格式Redis 提供了命令 EVAL script numkeys key [key …] arg [arg …] 其中 特性由于Redis对数据集单线程读写的特性,Lua脚本执行时会阻塞所有对数据集的读写操作,这给它带来了下面两个特性:
执行流程已 定义脚本函数 执行过的脚本可以根据hash值找到函数重新使用 Redis会根据传入的脚本内容生成函数,函数名由 function f_5332031c6b470dc5a0dd9b4bf2030dea6d65de91() return 'hello world' end 函数保存到 执行脚本函数
关于脚本超时介绍完EVAL命令,下面来关注Lua脚本长时间阻塞的风险。 Redis的配置文件中提供了如下配置项来规定最大执行时长
但这里有个坑,当一个脚本达到最大执行时长的时候,Redis并不会强制停止脚本的运行,仅仅在日志里打印个警告,告知有脚本超时。
为什么不能直接停掉呢? 因为 Redis 必须保证脚本执行的原子性,中途停止可能导致内存的数据集上只修改了部分数据。
如果时长达到 日志记录有脚本运行超时 开始允许接受其他客户端请求,但仅限于 其他请求仍返回busy错误 SCRIPT KILL 命令如果Lua只是读取数据而没做修改的话,执行 但是,如果脚本已经改写了数据内容,
SHUTDOWN NOSAVE 命令如上所述,如果脚本已经执行了写命令,
最后,不知道你有没有疑问,从开始执行脚本到 SHUTDOWN 之间的写命令会把日志写到AOF里吗?Lua脚本中的命令什么时候会写AOF里? 讲道理,既然 Redis 为了不破坏脚本的原子性而不让
下面就来验证这个猜测: 先执行 再开一个redis-cli 命令行执行一个内容如下的Lua脚本 redis.call('set','a','aaaa') --先执行写命令 local count = 1 while( 999999999 > count ) -- 阻塞几秒 do count = count+1 end 127.0.0.1:6379> eval "redis.call('set','a','aaaa') local count = 1 while( 999999999 > count ) do count = count+1 end" 0 (nil) (8.65s) 现象是,脚本刚开始执行,AOF文件毫无反应,一直等到8秒后脚本完成,命令才追加写入到AOF中。 这就验证了Redis脚本里的写命令是等到执行完成后再一次性写入AOF的。 参考到此这篇关于Redis中Lua脚本的使用和设置超时 的文章就介绍到这了,更多相关Redis Lua 超时内容请搜索极客世界以前的文章或继续浏览下面的相关文章希望大家以后多多支持极客世界! |
请发表评论