SpringSession Redis的存储结构以及清理策略
其中包含三个结构,
数据类型:hash
键名 spring:session:sessions:{sessionId}
数据:
creationTime 1404360000000 \
maxInactiveInterval 1800 \
lastAccessedTime 1404360000000 \
sessionAttr:attrName someAttrValue \
sessionAttr2:attrName someAttrValue2
数据类型:string
键名 spring:session:sessions:expires:{sessionId}
数据:
""
数据类型:set
键名 spring:session:expirations:{1439245080000}
数据:
expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe
expires:12312424-b496-1234-234f-345479d32f2s
当使用springsession redis创建一个新session时,会有以下步骤
HMSET spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe \
creationTime 1404360000000 \
maxInactiveInterval 1800 \
lastAccessedTime 1404360000000 \
sessionAttr:attrName someAttrValue \
sessionAttr2:attrName someAttrValue2
EXPIRE spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe 2100
APPEND spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe ""
EXPIRE spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe 1800
SADD spring:session:expirations:1439245080000 expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe
EXPIRE spring:session:expirations1439245080000 2100
第一句 HMSET …. someAttrValue2
- 会话ID是33fdd1b6-b496-4b33-9f7d-df96679d32fe。
- 该会话创建于1404360000000(从1970年1月1日格林尼治标准时间的午夜算起的毫秒)。
- 该会话在1800秒(30分钟)后到期。
- 该会话最后被访问的时间是1404360000000(自1970年1月1日格林尼治标准时间午夜起的毫秒数)。
- 该会话有两个属性。第一个是attrName,其值为someAttrValue。第二个会话属性名为attrName2,其值为someAttrValue2。
第二句 设置对应key的过期时间
💡 设置为会话实际过期后五分钟的过期时间(2100s)。以便在会话过期时可以访问会话的值。
第三四句 添加一个特殊的session expires key,设置过期时
💡 当session key被删除或过期时,触发 SessionDestroyedEvent。spring boot session redis 内部会处理相关消息,如下图
但是Redis用于清理过期key的后台任务属于低优先级任务,可能不会触发key过期。
为了保证发生过期事件,我们可以确保每个key在将要过期时被访问。这意味着,如果key的 TTL 已过期,在我们尝试访问该key时,会触发过期事件,Redis 会删除该密钥。
出于以上的原因,需要定期检查key是否过期,这里每分钟都会检查一次key
看下图Cleaning up日志
spring:session:expirations:{1439245080000}
下图为配置清理redis 过期 key 定时任务,需要关注的时cleanupExpiredSessions方法
具体处理过期key的方法,获取当前分钟(舍去秒和毫秒)的时间戳作为key的组成部分
Cleaning up 在这里出现了
获取key,拼接完成后为spring:session:expirations:
{expiration}
再获取当前 spring:sessions:expirations 中的 key list
获取到的sessionsToExpire值例子:
接下来在for循环中 拼接 如下 spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe
执行touch方法,如果到了过期时间,触发redis的删除操作