我正在使用NuGet RedisSessionStateProvider。
使用ASP.Net会话状态我正在使用以下内容从应用程序中使用会话数据:
public UserSessionData GetUserSessionData()
{
if (HttpContext.Current.Session == null || HttpContext.Current.Session["Key"] == null)
{
UserSessionData sessionData = ReadSessionFromDatabase();
HttpContext.Current.Session.Add("Key", sessionData);
return sessionData;
}
else
{
return (UserSessionData)HttpContext.Current.Session["Key"];
}
}
使用上述方法,第一次从数据库中读取值并存储在Session(Redis Cache)中。下次从Redis缓存中读取请求的值而不转到SQL。
工作正常。有时,当我需要使缓存的值无效并强制从数据库读取时,我调用HttpContext.Current.Session.Abandon()
。当用户更改他的计划时,这是作为示例完成的。
想象一下我需要使缓存无效的情况,因为数据库中的某些更改但是此更改不是用户的触发器。此更改由另一个网站(管理用户的某个内部网站)完成,或由Webhook(用户的计划更改通知)完成。如何强制用户重新从数据库中重新获取数据(删除缓存数据)什么时候不在HttpContext中触发?
我测试了使用flushdb
刷新所有redis缓存并且它有效。但是当然它会强制所有用户会话再次读取数据。如何仅为某些用户使缓存无效?
答案 0 :(得分:1)
如果你在应用程序内,你可以做Session.Abandon()。但是在这里你要从外部应用程序中删除Redis中的会话。只要您知道应用程序名称(您在web.config中提供的名称)和会话ID,就可以执行此操作。
会话数据作为_ 数据存储在Redis中,一些支持的内部数据存储在 内部。如果用户同时运行另一个页面,您可能会看到 _Write_Lock。
如果从Redis中删除所有三个,它基本上相当于执行Session.Abandon()。如果您打算使用StackExchange.Redis使用C#程序执行此操作,那么我建议使用LUA脚本将其删除,这样三个将立即删除,其他命令都无法干预。
您应该找到一个可以修改数据库条目的地方,并在必要时运行此代码。
string applicationName = "<Actual Application Name>";
string sessionId = "<Actual Session Id>";
RedisKey dataKey = String.Format("{0}_{1}_Data", applicationName, sessionId);
RedisKey internalKey = String.Format("{0}_{1}_Internal", applicationName, sessionId);
RedisKey writeLockKey = String.Format("{0}_{1}_Write_Lock", applicationName, sessionId);
RedisKey[] keys = new RedisKey[3];
keys[0] = dataKey;
keys[1] = internalKey;
keys[2] = writeLockKey;
string removeSessionScript = (@"
redis.call('DEL',KEYS[1])
redis.call('DEL',KEYS[2])
redis.call('DEL',KEYS[3])"
);
db.ScriptEvaluate(removeSessionScript, keys, null);