Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

同一个loginId多个SaSession对象使用set方法时,只有最后一个set方法生效问题 #735

Open
Andwxa opened this issue Feb 6, 2025 · 1 comment

Comments

@Andwxa
Copy link

Andwxa commented Feb 6, 2025

使用版本:

<sa-token>1.39.0</sa-token>

涉及的功能模块:

<artifactId>sa-token-alone-redis</artifactId>
<artifactId>sa-token-redis-fastjson2</artifactId>

测试步骤:

  • 我经过以下步骤测试:
// 获取指定id的SaSession
SaSession saSession = StpUtil.getSessionByLoginId(1, true);
// 断点运行完此行时redis有设置ROLE_LIST的内容
StpUtil.getSessionByLoginId(1, true).set(UserConst.ROLE_LIST, new String[]{"role"});
// 断点运行完此行时redis有设置PERMISSION_LIST的内容,但ROLE_LIST的内容消失
saSession.set(UserConst.PERMISSION_LIST, new String[]{"permission"});
  • 得出以下结果:
//源码
/**
 * 写值 
 * @param key   名称
 * @param value 值
 * @return 对象自身
 */
@Override
public SaSession set(String key, Object value) {
	dataMap.put(key, value);
	update();
	return this;
}
/**
 * 更新Session(从持久库更新刷新一下)
 */
public void update() {
	SaManager.getSaTokenDao().updateSession(this);
}

SaSession的set方法执行时内部update更新问题
1.要么全部重新获取保证是未被更改的Sasession

StpUtil.getSessionByLoginId(1, true).set(UserConst.ROLE_LIST, new String[]{"role"});
StpUtil.getSessionByLoginId(1, true).set(UserConst.PERMISSION_LIST, new String[]{"permission"});

2.要么一直沿用一个SaSession

SaSession saSession = StpUtil.getSessionByLoginId(1, true);
saSession.set(UserConst.ROLE_LIST, new String[]{"role"});
saSession.set(UserConst.PERMISSION_LIST, new String[]{"permission"});
  • 我的请求:
    如果可以请在文档写明set方法内部的update方法会更新之前保存的状态。
  • 可能的问题如下:
    内部update方法如果遇到多线程使用估计会导致有些未能更新至缓存;
    比如两个请求同时获取到原始SaSession对象;
    A请求的SaSession率先修改完成并且update,B请求的SaSession随后完成对应操作
    随后观测只有B请求生效了,而A请求未能生效
@Andwxa
Copy link
Author

Andwxa commented Feb 7, 2025

解决方法如下:
用户层面:使用一loginId为分布式锁保证同一时间只有一个请求对缓存进行更新
框架层面:我将提供一个思路,将缓存的键的细粒度提高,将缓存中loginId的dataMap等从loginId拿出来,使用键类型set方式将loginId和dataMap等进行绑定以便过期时间的同步,dataMap可以如上方法再次将键细粒度提高(如果嫌弃会导致占用额外的内存当我没说)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant