分布式并发场景下SpringSession(Redis) 的数据脏读问题

问题现象

问题来源于一个临时订单重复提交管控场景,通过在Session中写入本次提交的临时订单ID防止同个表单的重复提交。但在用户使用某些浏览器(如QQ浏览器、微信内置浏览器)时,仍有偶发性的重复提交现象。
相关核心代码如下:
分布式并发场景下SpringSession(Redis) 的数据脏读问题

原因分析

该问题主要原因是因为当有A、B两个一样的请求时,如果在A还没响应完毕的时候SpringMvc又接收了B请求,B请求在获取Session中的值时,会获取到A请求改写之前的数据。
其根本原因在于SpringSession在写入或删除Session属性时,会根据配置中的FlushMode决定在什么时候序列化到Redis,而默认的FlushMode为ON_SAVE,API原文是这样的:
分布式并发场景下SpringSession(Redis) 的数据脏读问题
也就是说,在默认情况下只有在Response被提交时Session内容才会序列化到Redis。所以导致了并发场景下的Session数据脏读问题

解决方案

目前我们采取将RedisFlushMode改为IMMEDIATE,修改方法为在@EnableRedisHttpSession注解中指定flushMode:
分布式并发场景下SpringSession(Redis) 的数据脏读问题
如此修改后,在每次调用removeAttribure后,都能正确的观察到Redis中相应的属性被置为空,问题也就基本得到了解决。

相关推荐