返回
Redis之Lua踩坑记
后端
2024-02-13 23:10:34
前言
Redis作为一款流行的NoSQL数据库,因其出色的性能和丰富的功能而受到广大开发者的青睐。本文将分享我在使用Redis的Lua脚本时踩过的坑,希望能够帮助大家避免同样的错误。
踩坑经历
事情的起因是一个记录文章阅读时长的接口,前端每秒钟轮询一次,后端根据阅读记录ID更新阅读记录时长。为了提高效率,我们决定使用Redis的Lua脚本来实现这个功能。
在Lua脚本中,我们首先通过hget
命令获取阅读记录的当前时长,然后通过hincrby
命令将阅读时长增加1秒,最后通过hset
命令更新阅读记录的时长。
-- 获取阅读记录的当前时长
local current_duration = redis.call('hget', 'reading_records', record_id)
-- 将阅读时长增加1秒
local new_duration = tonumber(current_duration) + 1
-- 更新阅读记录的时长
redis.call('hset', 'reading_records', record_id, new_duration)
这段脚本乍一看似乎没有什么问题,但实际上却存在一个严重的漏洞。
问题所在
问题在于,在使用hincrby
命令增加阅读时长时,我们没有对阅读时长进行类型检查。如果阅读记录的时长不是一个数字,那么hincrby
命令就会报错,导致整个脚本执行失败。
解决方案
为了解决这个问题,我们需要对阅读记录的时长进行类型检查,确保它是一个数字。如果阅读记录的时长不是一个数字,那么我们就需要将其转换为一个数字,然后再使用hincrby
命令增加阅读时长。
-- 获取阅读记录的当前时长
local current_duration = redis.call('hget', 'reading_records', record_id)
-- 将阅读时长转换为一个数字
if type(current_duration) ~= 'number' then
current_duration = tonumber(current_duration)
end
-- 将阅读时长增加1秒
local new_duration = current_duration + 1
-- 更新阅读记录的时长
redis.call('hset', 'reading_records', record_id, new_duration)
这样一来,我们就解决了这个问题,确保了脚本能够正确执行。
总结
通过这次踩坑经历,我深刻地认识到在使用Redis的Lua脚本时,一定要注意对数据类型进行检查,避免出现错误。