背景
常用的微服务架构如下图,在多个服务实例中需要获取到相同的session

Spring Redis Session 作为分布式共享Session的一种解决方案,现在已经被广泛的应用,项目的搭建这里不做介绍,主要看一看session 的在redis中的存储结构,为之后在RPC调用中传递session做准备
Redis中的存储结构
运行项目后,请求一次接口,进入redis中可以看到,多出来3组数据

Redis中的存储说明:
1、spring:session是默认的Redis HttpSession前缀(redis中,我们常用’:’作为分割符)。
2、每一个session都会创建3组数据
第一组:hash结构,spring-session存储的主要内容


hash结构有key和field,如上面的例子:hash的key为"spring:session:sessions"前缀加上fc454e71-c540-4097-8df2-92f88447063f,该key下的field有:
field=sessionAttr:key1,value=... //往session 设置的属性
field=sessionAttr:key2,value=... //往session 设置的属性根据实际情况可能会有多个
field=creationTime,value= //创建时间
field=maxInactiveInterval,value= //最大生存时间
field=lastAccessedTime,value= //最后访问时间
第二组:String结构,用于ttl过期时间记录

spring:session:sessions:expires:fc454e71-c540-4097-8df2-92f88447063f
key为“spring:session:sessions:expires:” 前缀+fc454e71-c540-4097-8df2-92f88447063f
value为空
第三组:set结构,过期时间记录

set的key固定为
“spring:session:expirations:1515135000000”
set的集合values为:
expires:c7fc28d7-5ae2-4077-bff2-5b2df6de11d8//一个会话一条
expires:fc454e71-c540-4097-8df2-92f88447063f//一个会话一条
简单提一下:redis清除过期key的行为是一个异步行为且是一个低优先级的行为,用文档中的原话来说便是,可能会导致session不被清除。于是引入了专门的expiresKey,来专门负责session的清除,包括我们自己在使用redis时也需要关注这一点。在开发层面,我们仅仅需要关注第三个key就行了。
数据获取
在一定场景下,我们需要根据获取到的sessionId来从redis中取到session中保存的数据,有以下两种方式
Redis Client
redis client方式直接获取
String sessionId = "spring:session:sessions:7002b5c0-3ae5-487a-873b-5838a4487ba3";Map<String, String> sessions = jedis.hgetAll(sessionId);Set<String> entrySet = sessions.keySet();JdkSerializationRedisSerializer jdk = new JdkSerializationRedisSerializer();for (String key : entrySet) {byte bytes[] = jedis.hget(sessionId.getBytes() , key.getBytes());Object value = jdk.deserialize(bytes);System.out.println(value.getClass() + "--" + key + "--" + value);}

RedisTemplate
通过spring 提供的redisTemplate来获取,
配置
在configuration中配置redisSessionTemplate,注意几个Serializer的配置,不匹配会导致读取出错
@Beanpublic <K,V> RedisTemplate<K, V> redisSessionTemplate(RedisConnectionFactory factory) {RedisTemplate<K, V> template = new RedisTemplate<>();// 配置连接工厂template.setConnectionFactory(factory);//JdkSerializationRedisSerializer jdkRedisSerializer = new JdkSerializationRedisSerializer();RedisSerializer<String> keySerializer = new StringRedisSerializer();RedisSerializer<Object> valueSerializer = new JdkSerializationRedisSerializer(this.getClass().getClassLoader());// 值采用json序列化template.setValueSerializer(valueSerializer);//使用StringRedisSerializer来序列化和反序列化redis的key值template.setKeySerializer(keySerializer);// 设置hash key 和value序列化模式template.setHashKeySerializer(keySerializer);template.setHashValueSerializer(valueSerializer);template.afterPropertiesSet();return template;}
获取
String sessionKey ="spring:session:sessions:" + sessionId;redisSessionTemplate.opsForHash().get(sessionKey, "sessionAttr:currentUser");redisSessionTemplate.opsForHash().get(sessionKey, "sessionAttr:loginAccount");





