Redis Lua 脚本调试是一种强大的工具,可以帮助您快速发现和解决Lua脚本中的问题。它允许您在运行脚本时逐步执行脚本,并检查每个步骤的结果。
从Redis 3.2开始,内置了 Lua debugger(简称LDB),使用Lua debugger可以很方便的对我们编写的Lua脚本进行调试
开启 lua dubegger ,将会进入debug命令行。这个模式下 redis 会 fork 一个进程进入隔离环境,不会影响 redis 正常提供服务,但调试期间,原始 redis 执行命令、脚本的结果也不会体现到 fork 之后的隔离环境之中
同步模式,这个模式下,会阻塞 redis 上所有的命令、脚本,直到脚本退出,完全模拟了正式环境使用时候的情况,使用的时候务必注意这点。
/data/lua # redis-cli -a 123456 --ldb --eval /data/lua/pong.luaWarning: Using a password with '-a' or '-u' option on the command line interface may not be safe.Lua debugging session started, please use:quit -- End the session.restart -- Restart the script in debug mode again.help -- Show Lua script debugging commands.* Stopped at 1, stop reason = step over-> 1 local foo = redis.call('ping') lua debugger>
pong.lua 脚本
local foo = redis.call('ping')return foo
图片
demo1.lua
local src = KEYS[1]local dst = KEYS[2]local count = tonumber(ARGV[1])return true
图片
lua debugger> print KEYS<value> {"list_a"; "list_b"; "10"}
打印所有的ARGV
lua debugger> print ARGV<value> {"10"}
local src = KEYS[1]local dst = KEYS[2]local count = tonumber(ARGV[1])-- 移除 list_a 列表的最后一个元素,返回值为移除的元素,即:elocal item = redis.call('rpop', src)-- 将 e 值插入到 list_b 列表表头部redis.call('lpush', dst, item)-- 返回 list_b 列表长度return redis.call('llen', dst)
准备数据
图片
图片
注意:KEYS 和 ARGV 使用 , 逗号分隔
local src = KEYS[1]local dst = KEYS[2]local count = tonumber(ARGV[1])while count > 0 do local item = redis.call('rpop', src) redis.debug("value of item: ",item); if item ~= false then redis.call('lpush', dst, item) end count = count - 1 endreturn redis.call('llen', dst)
图片
如果移除代码 count = count - 1 ,则会进入系循环
local src = KEYS[1]local dst = KEYS[2]local count = tonumber(ARGV[1])while count > 0 do local username = redis.call('get',src) redis.debug('username : ',username) local age = redis.call('get',dst) redis.debug('age : ',age) count = count - 1end
图片
lua debugger> b 7 6 local username = redis.call('get',src) #7 redis.debug('username : ',username) 8 local age = redis.call('get',dst)
图片
图片
图片
- 第 9 行打断点(b 9 ),查看所有代码,第9行已经被打伤断点了
图片
图片
图片
-- Copyright (C) ShaoBo Wan (Tinywan)local KEYS1 = KEYS[1]local KEYS2 = KEYS[2]local ARGV1 = ARGV[1]local ARGV2 = ARGV[2]local ARGV3 = ARGV[3]local ARGV4 = ARGV[4]local status, type = next(redis.call('TYPE', KEYS[1])) -- type=none status=ok if status ~= nil and status == 'ok' then if type == 'zset' then -- list = {"10090"; "10089"; "10088"; "10087"; "10086"} local list = redis.call('ZREVRANGEBYSCORE', KEYS[1], ARGV[1], ARGV[2], 'LIMIT', ARGV[3], ARGV[4]) -- 获取数组table长度:#list local kk = #list -- unpack它接受一个数组(table)作为参数,并默认从下标1开始返回数组的所有元素 local k1, k2, k3, k4 ,k5 = unpack(list) redis.debug('k1 ', k1) -- 10090 redis.debug('k2 ', k2) -- 10089 redis.debug('k3 ', k3) -- 10088 redis.debug('k4 ', k4) -- 10087 redis.debug('k5 ', k5) -- 10087 if list ~= nil and #list > 0 then -- ZREM key member [member ...] redis.call('ZREM', KEYS[1], unpack(list)) -- unpack(list) 返回过期数组的所有元素 -- HMGET key field [field ...] local result = redis.call('HMGET', KEYS[2], unpack(list)) -- ["username:Tinywan,age:24"] -- HDEL key field [field ...] redis.call('HDEL', KEYS[2], unpack(list)) -- 1 return result end endendreturn nil
如果该key不存在,则返回none
如果该key存在,则返回该key数据结构类型,如上返回 zset,表示有序集合。
图片
重要: 以上消费者脚本会直接删除有序集合key和所对应的哈希值。所以为了消息的可靠性。通过以上脚本返回的值会存储在一个stream流中,如果在stream消费失败(没有进行ACK机制),则会进入待办Pending队列重复消费(知道ACK机制或者删除该消息队列)
本文链接:http://www.28at.com/showinfo-26-59690-0.html深入理解 Redis Lua 脚本调试技巧和最佳实践
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
上一篇: 浅析五种 React 组件设计模式