`
m635674608
  • 浏览: 5042563 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

在RedisOperationsSessionRepository中清理会导致会话被错误地删除

 
阅读更多

https://github.com/spring-projects/spring-session/issues/92

    

 */
public class RedisOperationsSessionRepository implements SessionRepository<RedisOperationsSessionRepository.RedisSession> {
	/**
	 * The prefix for each key of the Redis Hash representing a single session. The suffix is the unique session id.
	 */
	static final String BOUNDED_HASH_KEY_PREFIX = "spring:session:sessions:";

	/**
	 * The key in the Hash representing {@link org.springframework.session.ExpiringSession#getCreationTime()}
	 */
	static final String CREATION_TIME_ATTR = "creationTime";

	/**
	 * The key in the Hash representing {@link org.springframework.session.ExpiringSession#getMaxInactiveIntervalInSeconds()}
	 */
	static final String MAX_INACTIVE_ATTR = "maxInactiveInterval";

	/**
	 * The key in the Hash representing {@link org.springframework.session.ExpiringSession#getLastAccessedTime()}
	 */
	static final String LAST_ACCESSED_ATTR = "lastAccessedTime";

	/**
	 * The prefix of the key for used for session attributes. The suffix is the name of the session attribute. For
	 * example, if the session contained an attribute named attributeName, then there would be an entry in the hash named
	 * sessionAttr:attributeName that mapped to its value.
	 */
	static final String SESSION_ATTR_PREFIX = "sessionAttr:";

	private final RedisOperations<String,ExpiringSession> sessionRedisOperations;

	private final RedisSessionExpirationPolicy expirationPolicy;

	/**
	 * If non-null, this value is used to override the default value for {@link RedisSession#setMaxInactiveIntervalInSeconds(int)}.
	 */
	private Integer defaultMaxInactiveInterval;

	/**
	 * Allows creating an instance and uses a default {@link RedisOperations} for both managing the session and the expirations.
	 *
	 * @param redisConnectionFactory the {@link RedisConnectionFactory} to use.
	 */
	@SuppressWarnings("unchecked")
	public RedisOperationsSessionRepository(RedisConnectionFactory redisConnectionFactory) {
		this(createDefaultTemplate(redisConnectionFactory));
	}

	/**
	 * Creates a new instance. For an example, refer to the class level javadoc.
	 *
	 * @param sessionRedisOperations The {@link RedisOperations} to use for managing the sessions. Cannot be null.
	 */
	public RedisOperationsSessionRepository(RedisOperations<String, ExpiringSession> sessionRedisOperations) {
		Assert.notNull(sessionRedisOperations, "sessionRedisOperations cannot be null");
		this.sessionRedisOperations = sessionRedisOperations;
		this.expirationPolicy = new RedisSessionExpirationPolicy(sessionRedisOperations);
	}

	/**
	 * Sets the maximum inactive interval in seconds between requests before newly created sessions will be
	 * invalidated. A negative time indicates that the session will never timeout. The default is 1800 (30 minutes).
	 *
	 *  @param defaultMaxInactiveInterval the number of seconds that the {@link Session} should be kept alive between
	 *                                    client requests.
	 */
	public void setDefaultMaxInactiveInterval(int defaultMaxInactiveInterval) {
		this.defaultMaxInactiveInterval = defaultMaxInactiveInterval;
	}

	public void save(RedisSession session) {
		session.saveDelta();
	}

	@Scheduled(cron="0 * * * * *")
	public void cleanupExpiredSessions() {
		this.expirationPolicy.cleanExpiredSessions();
	}

	public RedisSession getSession(String id) {
		return getSession(id, false);
	}

 

 

pring Session依赖于Redis 的删除和过期密钥空间通知,分别触发SessionDeletedEvent和SessionExpiredEvent。它是SessionDeletedEvent或SessionExpiredEvent,以确保与会议相关的资源将会被清理。例如,当使用Spring Session的WebSocket支持时,Redis过期或删除事件是什么触发与会话关联的任何WebSocket连接。

会话密钥本身不直接跟踪到期时间,因为这将意味着会话数据将不再可用。而是使用特殊的会话到期密钥。在我们的例子中,到期关键是:

APPEND spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe“”
EXPIRE spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe 1800
当会话到期时,密钥被删除或到期,密钥空间通知触发实际会话的查找,并触发一个SessionDestroyedEvent。

仅依靠Redis到期的一个问题是,Redis不保证何时未通过密钥访问过期的事件。具体来说,Redis用于清除过期密钥的后台任务是低优先级任务,可能不会触发密钥到期。有关其他详细信息,请参阅Redis文档中的过期事件时间段。

为了规避过期事件不能保证发生的事实,我们可以确保在预期到期时访问每个密钥。这意味着如果TTL在该键上过期,当我们尝试访问它们的键时,Redis将删除该键并触发过期的事件。

因此,每个会话到期也跟踪到最近的分钟。这允许后台任务访问潜在的过期会话,以确保以更确定性的方式触发Redis过期事件。例如:

SADD spring:session:expirations:1439245080000 expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe
EXPIRE spring:session:expirations1439245080000 2100
后台任务将使用这些映射来明确地请求每个密钥。通过访问他们的密钥而不是删除它们,我们确保只有当TTL过期时,Redis才会删除该密钥。

我们没有明确删除密钥,因为在某些情况下,可能存在不正确地将密钥识别为过期的竞争条件。没有使用分布式锁(这会杀死我们的性能),没有办法确保到期映射的一致性。通过简单的访问密钥,我们确保该密钥只有在该密钥的TTL过期时才被删除。

 

spring session 文档

 

https://docs.spring.io/spring-session/docs/current/reference/html5/

分享到:
评论

相关推荐

    定时清除XP会话连接

    标题中的“定时清除XP会话连接”指的是针对Windows XP操作系统的一种优化策略,主要是解决系统由于过多的远程桌面或网络共享连接导致的问题。Windows XP默认情况下,最多只能支持10个并发的远程桌面会话,这对于需要...

    maya插件清理工具

    这在长期使用Maya并频繁尝试新插件的用户中尤为重要,因为他们可能忘记卸载一些临时测试的插件,这些插件可能会在后台占用资源,影响整体性能。 插件清理工具的操作流程一般包括以下步骤: 1. **扫描插件**:工具...

    Oracle错误:动态执行表不可访问,本会话自动统计被禁止,关闭自动统计之后的问题

    在使用PL/SQL Developer或类似工具连接到Oracle数据库的过程中,用户可能会遇到一个错误提示:“动态执行表不可访问,本会话的自动统计被禁止”。这一错误通常伴随着对几个特定视图(如`V$SESSION`、`V$SESSTAT`和`V...

    crt批量添加会话

    4. 使用CRT管理设备:现在,使用CRT连接到这些设备,CRT将自动加载配置文件,并显示在会话表中。你可以根据需要,选择要连接的设备,并执行相应的命令。 CRT批量添加会话的优点: * 高效:使用CRT批量添加会话,...

    F5负载均衡会话保持

    会话保持在负载均衡中的作用在于维持用户与特定服务器间的关联性,避免因为负载均衡策略导致用户在多台服务器间频繁切换,从而影响服务质量和用户体验。例如,在需要用户登录的系统中,如果用户请求被分发到不同的...

    局域网空闲共享会话清除BAT

    局域网空闲共享会话清除BAT,清除多余的共享会话,解决共享无法连接

    在asp.net中实现会话状态基础

    2. **StateServer模式**:在这种模式下,会话状态被存储在一个单独的进程(`aspnet_state.exe`)中,该进程可以运行在同一台计算机上,也可以运行在另一台计算机上。这种方式非常适合需要跨多台服务器共享会话状态的...

    JSP中会话跟踪的操作

    默认情况下,会话会在浏览器关闭时失效,但也可以通过`setMaxInactiveInterval()`自定义。 2. **敏感数据**:不建议将敏感信息如密码、信用卡号等存储在会话中,因为它们可能会被恶意用户获取。 3. **会话劫持**:...

    Struts2解决未更新会话标识

    3. **Struts2的SessionAware接口**:如果Action类实现了SessionAware接口,Struts2会在调用Action的execute方法之前,自动将HttpSession注入到Action实例中。这样,开发者就可以直接在Action中操作会话,实现会话...

    asp.net 会话状态

    ASP.NET 会话状态是Web开发中用于保持用户在浏览多页应用时的状态信息的关键机制。由于HTTP协议的无状态特性,服务器无法自动记住不同请求之间的用户信息。为了解决这个问题,ASP.NET提供了会话状态功能,使得开发者...

    DB2 归档日志清理

    在DB2中,日志是用于记录数据库中所有事务活动的重要组件,包括所有的修改操作(如插入、更新和删除)。为了保证数据的一致性和完整性,DB2通过日志机制实现了数据恢复功能。然而,随着时间的推移,日志文件会不断...

    如何在ASP和ASP.NET中共享会话状态

    比如,OnInit方法会在页面初始化时调用,用于设置Page对象的初始化状态。当用户请求页面时,如果他们还没有被分配一个mySession Cookie,那么就会被发放一个新的Cookie。当请求结束并且页面卸载时,会调用Unload方法...

    windows会话管理程序

    会话管理在Windows中主要由服务控制管理器(Service Control Manager)和终端服务(Terminal Services,现在被称为远程桌面服务,Remote Desktop Services,RDS)组件协同完成。当用户登录到系统时,一个会话就会被...

    UE注册-建立会话-释放会话-UE注销信令流程.pdf

    在 UE 注册流程中,PFCP 会话修改响应(PFCP Session Modification Response)是 UE 与网络之间的关键交互步骤。该步骤中,UE 将发送 PFCP 关联设置请求(PFCP Association Setup Request),以便建立与网络的连接。...

    F5负载均衡会话保持技术及原理技术白皮书.docx

    会话保持是指在负载均衡器上有这么一种机制,可以识别客户与服务器之间交互过程的关连性,在作负载均衡的同时,还保证一系列相关连的访问请求会保持分配到一台服务器上。会话保持技术是负载均衡器的一种重要功能,...

    Oracle经典故障解析 连接数&会话数

    在使用Oracle数据库的过程中,连接数和会话数是影响系统性能的关键因素。下面将详细解析这两个概念,以及它们在Oracle故障排查中的重要性。 1. 连接数和会话数的概念:在Oracle中,连接数指的是同一时间连接到...

Global site tag (gtag.js) - Google Analytics