/** * <p> * A {@link org.springframework.session.SessionRepository} that is implemented using * Spring Data's {@link org.springframework.data.redis.core.RedisOperations}. In a web * environment, this is typically used in combination with {@link SessionRepositoryFilter} * . This implementation supports {@link SessionDeletedEvent} and * {@link SessionExpiredEvent} by implementing {@link MessageListener}. * </p> * * <h2>Creating a new instance</h2> * * A typical example of how to create a new instance can be seen below: * * <pre> * JedisConnectionFactory factory = new JedisConnectionFactory(); * * RedisOperationsSessionRepository redisSessionRepository = new RedisOperationsSessionRepository(factory); * </pre> * * <p> * For additional information on how to create a RedisTemplate, refer to the * <a href = "http://docs.spring.io/spring-data/data-redis/docs/current/reference/html/" > * Spring Data Redis Reference</a>. * </p> * * <h2>Storage Details</h2> * * The sections below outline how Redis is updated for each operation. An example of * creating a new session can be found below. The subsequent sections describe the * details. * * <pre> * 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 * </pre> * * <h3>Saving a Session</h3> * * <p> * Each session is stored in Redis as a * <a href="http://redis.io/topics/data-types#hashes">Hash</a>. Each session is set and * updated using the <a href="http://redis.io/commands/hmset">HMSET command</a>. An * example of how each session is stored can be seen below. * </p> * * <pre> * HMSET spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe creationTime 1404360000000 maxInactiveInterval 1800 lastAccessedTime 1404360000000 sessionAttr:attrName someAttrValue sessionAttr:attrName2 someAttrValue2 * </pre> * * <p> * In this example, the session following statements are true about the session: * </p> * <ul> * <li>The session id is 33fdd1b6-b496-4b33-9f7d-df96679d32fe</li> * <li>The session was created at 1404360000000 in milliseconds since midnight of 1/1/1970 * GMT.</li> * <li>The session expires in 1800 seconds (30 minutes).</li> * <li>The session was last accessed at 1404360000000 in milliseconds since midnight of * 1/1/1970 GMT.</li> * <li>The session has two attributes. The first is "attrName" with the value of * "someAttrValue". The second session attribute is named "attrName2" with the value of * "someAttrValue2".</li> * </ul> * * * <h3>Optimized Writes</h3> * * <p> * The {@link RedisSession} keeps track of the properties that have changed and only * updates those. This means if an attribute is written once and read many times we only * need to write that attribute once. For example, assume the session attribute * "sessionAttr2" from earlier was updated. The following would be executed upon saving: * </p> * * <pre> * HMSET spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe sessionAttr:attrName2 newValue * </pre> * * <h3>SessionCreatedEvent</h3> * * <p> * When a session is created an event is sent to Redis with the channel of * "spring:session:channel:created:33fdd1b6-b496-4b33-9f7d-df96679d32fe" such that * "33fdd1b6-b496-4b33-9f7d-df96679d32fe" is the sesion id. The body of the event will be * the session that was created. * </p> * * <p> * If registered as a {@link MessageListener}, then * {@link RedisOperationsSessionRepository} will then translate the Redis message into a * {@link SessionCreatedEvent}. * </p> * * <h3>Expiration</h3> * * <p> * An expiration is associated to each session using the * <a href="http://redis.io/commands/expire">EXPIRE command</a> based upon the * {@link org.springframework.session.data.redis.RedisOperationsSessionRepository.RedisSession#getMaxInactiveIntervalInSeconds()} * . For example: * </p> * * <pre> * EXPIRE spring:session:sessions:33fdd1b6-b496-4b33-9f7d-df96679d32fe 2100 * </pre> * * <p> * You will note that the expiration that is set is 5 minutes after the session actually * expires. This is necessary so that the value of the session can be accessed when the * session expires. An expiration is set on the session itself five minutes after it * actually expires to ensure it is cleaned up, but only after we perform any necessary * processing. * </p> * * <p> * <b>NOTE:</b> The {@link #getSession(String)} method ensures that no expired sessions * will be returned. This means there is no need to check the expiration before using a * session * </p> * * <p> * Spring Session relies on the expired and delete * <a href="http://redis.io/topics/notifications">keyspace notifications</a> from Redis to * fire a SessionDestroyedEvent. It is the SessionDestroyedEvent that ensures resources * associated with the Session are cleaned up. For example, when using Spring Session's * WebSocket support the Redis expired or delete event is what triggers any WebSocket * connections associated with the session to be closed. * </p> * * <p> * Expiration is not tracked directly on the session key itself since this would mean the * session data would no longer be available. Instead a special session expires key is * used. In our example the expires key is: * </p> * * <pre> * APPEND spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe "" * EXPIRE spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe 1800 * </pre> * * <p> * When a session expires key is deleted or expires, the keyspace notification triggers a * lookup of the actual session and a {@link SessionDestroyedEvent} is fired. * </p> * * <p> * One problem with relying on Redis expiration exclusively is that Redis makes no * guarantee of when the expired event will be fired if they key has not been accessed. * Specifically the background task that Redis uses to clean up expired keys is a low * priority task and may not trigger the key expiration. For additional details see * <a href="http://redis.io/topics/notifications">Timing of expired events</a> section in * the Redis documentation. * </p> * * <p> * To circumvent the fact that expired events are not guaranteed to happen we can ensure * that each key is accessed when it is expected to expire. This means that if the TTL is * expired on the key, Redis will remove the key and fire the expired event when we try to * access they key. * </p> * * <p> * For this reason, each session expiration is also tracked to the nearest minute. This * allows a background task to access the potentially expired sessions to ensure that * Redis expired events are fired in a more deterministic fashion. For example: * </p> * * <pre> * SADD spring:session:expirations:1439245080000 expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe * EXPIRE spring:session:expirations1439245080000 2100 * </pre> * * <p> * The background task will then use these mappings to explicitly request each session * expires key. By accessing the key, rather than deleting it, we ensure that Redis * deletes the key for us only if the TTL is expired. * </p> * <p> * <b>NOTE</b>: We do not explicitly delete the keys since in some instances there may be * a race condition that incorrectly identifies a key as expired when it is not. Short of * using distributed locks (which would kill our performance) there is no way to ensure * the consistency of the expiration mapping. By simply accessing the key, we ensure that * the key is only removed if the TTL on that key is expired. * </p> * * @author Rob Winch * @since 1.0 */ public class RedisOperationsSessionRepository implements FindByIndexNameSessionRepository<RedisOperationsSessionRepository.RedisSession>, MessageListener {
public void delete(String sessionId) {
RedisSession session = getSession(sessionId, true);
if (session == null) {
return;
}
cleanupPrincipalIndex(session);
this.expirationPolicy.onDelete(session);
String expireKey = getExpiredKey(session.getId());
this.sessionRedisOperations.delete(expireKey);
session.setMaxInactiveIntervalInSeconds(0);
save(session);
}
spring session 3 个 key 意义 以及注意事项
1.真正配置缓解的key,用户监控key缓存失效,触发session失效事件
spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe 1800
2.类似hash session相关信息,最近访问时间,到期时间 session.setAttribute
//该SessionRepository.getSession(String)方法确保不会返回到期的会话。有个判断
spring:session:sessions:5b29c067-a4b1-4d51-98b2-be084703fc78 210
3.
set 1497195000000 时间点到期的session key set ,
org.springframework.session.data.redis.RedisOperationsSessionRepository.cleanupExpiredSessions()
定时清理该key,并且访问spring:session:sessions确保ttl任务优先级
spring:session:expirations:1497195000000 210
4.事件:
通过SessionEventHttpSessionListenerAdapter listeners事件redis key 失效删除事件,监控 创建和失效session事件
5.退出登录:
通过session invalidate 方法,失效session退出登录,删除前两个key,并且设置第三个key过期时间
1.真正配置缓解的key,用户监控key缓存失效,触发session失效事件
spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe 1800
2.类似hash session相关信息,最近访问时间,到期时间 session.setAttribute
//该SessionRepository.getSession(String)方法确保不会返回到期的会话。有个判断
spring:session:sessions:5b29c067-a4b1-4d51-98b2-be084703fc78 210
3.
set 1497195000000 时间点到期的session key set ,
org.springframework.session.data.redis.RedisOperationsSessionRepository.cleanupExpiredSessions()
定时清理该key,并且访问spring:session:sessions确保ttl任务优先级
spring:session:expirations:1497195000000 210
4.事件:
通过SessionEventHttpSessionListenerAdapter listeners事件redis key 失效删除事件,监控 创建和失效session事件
5.退出登录:
通过session invalidate 方法,失效session退出登录,删除前两个key,并且设置第三个key过期时间
相关推荐
在本场景中,我们将讨论如何利用 SpringSession 将 Tomcat 的 session 数据同步到 Redis 数据库存储,以实现高可用性和可扩展性的架构。 首先,理解为什么要使用 SpringSession 和 Redis。在传统的 web 应用中,...
本项目“Springboot+SpringSecurity+SpringSession+Redis+Mybatis-Plus+Swwager”整合了Spring Boot、Spring Security、Spring Session、Redis、Mybatis-Plus以及Swagger等技术,旨在构建一个强大的、安全的、具有...
Spring-Redis-Session 自定义 key 和过期时间 ...Spring-Redis-Session 提供了一个灵活的会话管理机制,允许开发者自定义 key 和过期时间,且使用 Redis 作为会话存储介质,提供了高性能和高可扩展性的解决方案。
使用Spring Session,开发者可以配置Spring Boot应用,将Session存储到Redis中。配置主要涉及以下几个步骤: - 添加Spring Session和Redis相关依赖。 - 配置Spring Session,指定使用Redis作为Session存储。 - ...
- 配置Spring Session:在Spring Boot的配置类中启用Spring Session,并指定使用Redis作为存储机制。 - 定制Session序列化:根据业务需求,可能需要自定义Session的序列化方式,以确保所有数据都能正确存储和恢复...
标题中的“springboot通过redis共享session”涉及到的是在Spring Boot应用中使用Redis作为session存储的解决方案。这通常是为了实现分布式环境下的用户会话共享,确保用户在不同服务器之间切换时仍能保持登录状态。...
Spring Data Redis是一个强大的Java库,它是Spring Data项目的一部分,旨在简化与Redis内存数据存储的集成。Redis是一个开源的、高性能的键值数据存储系统,常用于数据库、缓存和消息中间件。Spring Data Redis提供...
spring.session.redis.key-prefix=sess: ``` 3. 自定义Session管理:在Spring Boot应用中,创建一个`WebMvcConfigurerAdapter`的子类,重写`addSessionAttributes`方法,注册需要在Session中保存的属性。 ```java ...
只需要使用标准的servlet API调用session,在底层就会通过Spring Session得到的,并且会存储到Redis或其他你所选择的数据源中。 以下是一个简单的示例代码: ``` @Controller @RequestMapping(value = "index") ...
例如,我们可以通过`session.setAttribute("key", "value")`来存储数据,`session.getAttribute("key")`来获取数据,以及`session.invalidate()`来结束一个会话。Session的主要优点在于它可以跨多个页面保持用户状态...
Redis作为一个高性能的Key-Value数据库,对于存储和检索Session数据非常高效,是实现Session跨域共享的理想选择。在实际项目中,可以根据具体需求调整配置和实现细节,以达到最佳性能和安全性。
在Web开发中,session是一种服务器端存储用户状态的方式。当用户打开浏览器访问网站时,服务器会为该用户分配一个唯一的session ID,将其保存在客户端的cookie中,然后服务器通过这个ID识别并跟踪用户的会话状态。 ...
5. **Spring Session框架**:Spring社区提供了一个名为Spring Session的项目,它支持多种后端存储(如Redis、MongoDB等),并且与Spring MVC无缝集成,简化了分布式Session的配置和使用。 6. **HTTP Session Sticky...
4. **Session存储**:每当有新的Session创建或已有Session的属性发生变化时,监听器会调用相应的方法,我们将Session ID及Session内容序列化为字符串,然后存入Redis,键(key)可以设置为`session:` + Session ID。...
在分布式系统中,Session管理是一个重要的挑战,因为传统的Session存储在单个服务器的内存中,无法在多台服务器之间共享。Spring与Redis结合提供了一种有效的解决方案,实现了Session的分布式管理,使得用户在不同...
本篇文章主要介绍了如何在Spring Boot项目中加入Redis来实现对session的存储与管理。 一、Spring Boot项目中加入Redis 首先,我们需要使用Spring Initializr来新建一个Spring Boot项目。在pom.xml中添加Redis和...
`key`属性定义了一个密钥,用于加密存储在Cookie中的数据。`token-validity-seconds`属性则指定了Cookie的有效期,以秒为单位。例如,如果设置为`18000`,那么Cookie将在5小时内有效。 此外,还可以通过自定义`...
在实际开发中,有些框架如Spring已经内置了对ThreadLocal的管理和清理机制,可以更方便地在多线程环境中使用session。 总结,ThreadLocal是Java中处理线程局部数据的利器,特别适用于需要线程隔离的场景,如Web...
它的高速读写性能使得它成为存储Session的理想选择,尤其是在分布式环境中,可以将Session数据集中存储,便于多台服务器共享。 将Shiro与Redis整合进行Session管理的过程主要包括以下几个步骤: 1. **配置...
此外,Spring Boot还支持使用Redis作为Session的存储,通过`spring-session-data-redis`模块,可以将用户的会话信息持久化到Redis中,从而实现分布式会话管理。这样,用户在不同服务器之间切换时,会话信息仍能保持...