sessionId不为空的情况下,会先比较sessionId是否等于currentSessionId中的sessionId,如果等于则从currentSession中取出session,currentSessionId和currentSession都是ThreadLocal变量,这里并没有直接从redis里面取数据,如果同一线程没有去处理其他用户信息,是可以直接从内存中取出的,提高了性能;最后才从redis里面获取数据,从redis里面获取的是一段二进制数据,需要进行反序列化操作,相关序列化和反序列化都在JavaSerializer类中:
public void deserializeInto(byte[] data, RedisSession session, SessionSerializationMetadata metadata)
throws IOException, ClassNotFoundException {
BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(data));
Throwable arg4 = null;
try {
CustomObjectInputStream x2 = new CustomObjectInputStream(bis, this.loader);
Throwable arg6 = null;
try {
SessionSerializationMetadata x21 = (SessionSerializationMetadata) x2.readObject();
metadata.copyFieldsFrom(x21);
session.readObjectData(x2);
} catch (Throwable arg29) {
......
}
二进制数据中保存了2个对象,分别是SessionSerializationMetadata和RedisSession,SessionSerializationMetadata里面保存的是Session中的attributes信息,RedisSession其实也有attributes数据,相当于这份数据保存了2份;
2.如何创建
同样RedisSessionManager重写了createSession方法,2个重要的点分别:sessionId的唯一性问题和session保存到redis中;
// Ensure generation of a unique session identifier.
if (null != requestedSessionId) {
sessionId = sessionIdWithJvmRoute(requestedSessionId, jvmRoute);
if (jedis.setnx(sessionId.getBytes(), NULL_SESSION) == 0L) {
sessionId = null;
}
} else {
do {
sessionId = sessionIdWithJvmRoute(generateSessionId(), jvmRoute);
} while (jedis.setnx(sessionId.getBytes(), NULL_SESSION) == 0L); // 1 = key set; 0 = key already existed
}
分布式环境下有可能出现生成的sessionId相同的情况,所以需要确保唯一性;保存session到redis中是最核心的一个方法,何时更新,何时过期都在此方法中处理;
3.何时更新到redis
具体看saveInternal方法
protected boolean saveInternal(Jedis jedis, Session session, boolean forceSave) throws IOException {
Boolean error = true;
try {
log.trace("Saving session " + session + " into Redis");
RedisSession redisSession = (RedisSession)session;
if (log.isTraceEnabled()) {
log.trace("Session Contents [" + redisSession.getId() + "]:");
Enumeration en = redisSession.getAttributeNames();
while(en.hasMoreElements()) {
log.trace(" " + en.nextElement());
}
}
byte[] binaryId = redisSession.getId().getBytes();
Boolean isCurrentSessionPersisted;
SessionSerializationMetadata sessionSerializationMetadata = currentSessionSerializationMetadata.get();
byte[] originalSessionAttributesHash = sessionSerializationMetadata.getSessionAttributesHash();
byte[] sessionAttributesHash = null;
if (
forceSave
|| redisSession.isDirty()
|| null == (isCurrentSessionPersisted = this.currentSessionIsPersisted.get())
|| !isCurrentSessionPersisted
|| !Arrays.equals(originalSessionAttributesHash, (sessionAttributesHash = serializer.attributesHashFrom(redisSession)))
) {
log.trace("Save was determined to be necessary");
if (null == sessionAttributesHash) {
sessionAttributesHash = serializer.attributesHashFrom(redisSession);
}
SessionSerializationMetadata updatedSerializationMetadata = new SessionSerializationMetadata();
updatedSerializationMetadata.setSessionAttributesHash(sessionAttributesHash);
jedis.set(binaryId, serializer.serializeFrom(redisSession, updatedSerializationMetadata));
redisSession.resetDirtyTracking();
currentSessionSerializationMetadata.set(updatedSerializationMetadata);
currentSessionIsPersisted.set(true);
} else {
log.trace("Save was determined to be unnecessary");
}
log.trace("Setting expire timeout on session [" + redisSession.getId() + "] to " + getMaxInactiveInterval());
jedis.expire(binaryId, getMaxInactiveInterval());
error = false;
return error;
} catch (IOException e) {
log.error(e.getMessage());
throw e;
} finally {
return error;
}
}









