Redis Lua脚本书写

目录

1. 级联缓存值

1.1 级联缓存session及相关信息

lua脚本语句

redis运行示例

2. 级联查询

2.1 级联查询session

lua脚本语句

redis运行示例

3. 级联更新

3.1 级联更新accountId对应的用户信息

lua脚本

redis运行示例

 4. 级联续期

4.1 刷新session时级联续期

 lua脚本

redis运行结果

5. 级联删除

5.1 级联删除session

 lua脚本语句

redis运行示例


场景介绍:

(1)web项目中一般会在redis中存sessionId对应的用户信息,保存sessionId—>userInfo的关联关系。

(2)实际开发中有需要根据accountId查询用户缓存的信息,而步骤1只保存了sessionId到userInfo的映射关系。那么如何通过acccountId找到redis中缓存的用户信息呢?要么根据accountId多存一份,但太浪费资源了。这时我们可以通过accountId——映射—>sessionId——映射—>userinfo的链路确定用户信息,利用redis的lua脚本做级联的操作。​

1. 级联缓存值


1.1 级联缓存session及相关信息

(1)缓存session值,即根据sessionId缓存用户信息字符串。
(2)待第一步成功后,缓存accountId,即key为accountId,值为sessionId。

lua脚本语句

local sessionkey = KEYS[1]
local userInfo = ARGV[1] 
local accountId = KEYS[2] 

redis.call('SET', sessionkey, userInfo) 
local result =redis.call('SET', accountId, sessionkey)

return result

注:第一个set执行完,恰好redis挂了,第二个set无法正常执行返回结果,代码中执行lua脚本需要考虑超时时间。

redis运行示例

eval "local sessionkey = KEYS[1] local userInfo = ARGV[1] local accountId = KEYS[2] redis.call('SET', sessionkey, userInfo) local result =redis.call('SET', accountId, sessionkey) return result" 2 aa cc qq

Redis Lua脚本书写_第1张图片

 注:这里2暂时理解为2个key,aa=sessionId,cc=accountId,qq=userInfo。即套用以下公式在redis中执行lua脚本。

EVAL script numkeys key [key …] arg [arg …]

2. 级联查询

2.1 级联查询session

(1)根据accountId查询sessionId

(2)根据sessionId查询用户信息,中间需要判断

lua脚本语句

local accountId = KEYS[1]

local sessionId = redis.call('GET', accountId)

if sessionId then
    local userInfoString = redis.call('GET', sessionId)
    return userInfoString
else
    return nil
end

redis运行示例

eval "local accountId = KEYS[1] local sessionId = redis.call('GET', accountId) if sessionId then local userInfoString = redis.call('GET', sessionId) return userInfoString else return nil end" 1 cc

根据accountId(值cc),找到sessionId(值aa)对应的用户信息qq。

 查找一个不存在的值.

3. 级联更新

3.1 级联更新accountId对应的用户信息

(1)先查询accountId是否存在对应的sessionId

(2)若存在,则更新缓存的用户信息,不存在则报错提示

lua脚本

local accountId = KEYS[1] 
local userInfoString = ARGV[1]

local sessionId = redis.call('GET', accountId) 

if sessionId then 
  redis.call('SET', sessionId, userInfoString) 
  return 1 
else 
return 0 
end

redis运行示例

eval "local accountId = KEYS[1] local userInfoString = ARGV[1] local sessionId = redis.call('GET', accountId) if sessionId then redis.call('SET', sessionId, userInfoString) return 1 else return 0 end" 1 cc newUserInfoString

正常情况更新一条信息

不正常没有更新对应的信息

 4. 级联续期

4.1 刷新session时级联续期

(1)为sessionId进行续期,查询到accountId

(2)再为accountId进行续期

redis lua脚本为不存在的值进行续期,返回0,不报错。因此考虑可以先不查询,直接续期。当然实际使用中,刷新session的用户信息缓存时,绝大部分存在key。

 lua脚本

local sessionId = KEYS[1] 
local ttl = tonumber(ARGV[1]) 

local accountId=redis.call('GET', sessionId)    

if accountId then
	local accountResult=redis.call('EXPIRE', accountId,ttl) 
	local sessionResult=redis.call('EXPIRE', sessionId,ttl) 
	
	return accountResult+sessionResult
end
return 0          

PS:实际上用户信息如果存字符串,以上的lua脚本考虑做字符串处理,从用户信息字符串获取accountId,再为accountId对应的sessionId映射续期。

redis运行结果

eval "local sessionId = KEYS[1] local ttl = tonumber(ARGV[1]) local accountId=redis.call('GET', sessionId) if accountId then local accountResult=redis.call('EXPIRE', accountId,ttl) local sessionResult=redis.call('EXPIRE', sessionId,ttl) return accountResult+sessionResult end return 0" 1 sessionId111 120

5. 级联删除

5.1 级联删除session

(1)删除sessionId对应的缓存的用户信息

(2)再根据accountId删除对应的映射关系

删除存在的key返回1,不存在的key返回0

 lua脚本语句

local sessionId = KEYS[1] 
local accountId = KEYS[2]
local sessionResult=redis.call('DEL', sessionId) 
local accountResult=redis.call('DEL', accountId) 
return sessionResult+accountResult

redis运行示例

eval "local sessionId = KEYS[1] local accountId = KEYS[2] local sessionResult=redis.call('DEL', sessionId) local accountResult=redis.call('DEL', accountId) return sessionResult+accountResult" 2 iii lll

 最后,实际缓存的用户信息并不一定是字符串。缓存字符串速度快,占用空间小,但需要在代码中序列化。缓存对象,占用空间大,速度较前者慢,使用时便捷无须转换。或考虑使用Hash的数据结构。

你可能感兴趣的:(redis,lua,数据库)