目录
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)缓存session值,即根据sessionId缓存用户信息字符串。
(2)待第一步成功后,缓存accountId,即key为accountId,值为sessionId。
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脚本需要考虑超时时间。
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
注:这里2暂时理解为2个key,aa=sessionId,cc=accountId,qq=userInfo。即套用以下公式在redis中执行lua脚本。
EVAL script numkeys key [key …] arg [arg …]
(1)根据accountId查询sessionId
(2)根据sessionId查询用户信息,中间需要判断
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
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。
查找一个不存在的值.
(1)先查询accountId是否存在对应的sessionId
(2)若存在,则更新缓存的用户信息,不存在则报错提示
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
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
正常情况更新一条信息
不正常没有更新对应的信息
(1)为sessionId进行续期,查询到accountId
(2)再为accountId进行续期
redis lua脚本为不存在的值进行续期,返回0,不报错。因此考虑可以先不查询,直接续期。当然实际使用中,刷新session的用户信息缓存时,绝大部分存在key。
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映射续期。
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
(1)删除sessionId对应的缓存的用户信息
(2)再根据accountId删除对应的映射关系
删除存在的key返回1,不存在的key返回0
local sessionId = KEYS[1]
local accountId = KEYS[2]
local sessionResult=redis.call('DEL', sessionId)
local accountResult=redis.call('DEL', accountId)
return sessionResult+accountResult
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的数据结构。