温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

分布式中Redis是怎样实现Session

发布时间:2021-12-17 16:17:45 来源:亿速云 阅读:129 作者:柒染 栏目:大数据

本篇文章为大家展示了分布式中Redis是怎样实现Session,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

这里我要使用的是网友提供给的一种方自定义Session,需要继承System.Web.SessionState.SessionStateStoreProviderBase实现自己的SessionStateStoreProvide,下面讲解如何实现自定义的RedisSessionStateStore。

SessionStateStoreProviderBase

  SessionStateStoreProviderBase是asp.net提供的定义数据存储区的会话状态提供程序所需的成员。像常用InProcSessionStateStore(mode="InProc"),SqlSessionStateStore(mode="SQLServer"),都是继承SessionStateStoreProviderBase实现的存储。我们来看看msdn对其成员的定义

成员说明

InitializeRequest 方法

执行会话状态存储提供程序必需的所有初始化操作。

EndRequest 方法

执行会话状态存储提供程序必需的所有清理操作。

Dispose 方法

释放会话状态存储提供程序不再使用的所有资源。

GetItemExclusive 方法

从会话数据存储区中检索会话的值和信息,并在请求持续期间锁定数据存储区中的会话项数据。GetItemExclusive 方法设置几个输出参数值,这些参数值将数据存储区中当前会话状态项的状态通知给执行调用的 SessionStateModule

如果数据存储区中未找到任何会话项数据,则GetItemExclusive 方法将 locked 输出参数设置为false,并返回 null。这将导致 SessionStateModule调用 CreateNewStoreData 方法来为请求创建一个新的SessionStateStoreData 对象。

如果在数据存储区中找到会话项数据但该数据已锁定,则GetItemExclusive 方法将 locked 输出参数设置为true,将 lockAge 输出参数设置为当前日期和时间与该项锁定日期和时间的差,将 lockId 输出参数设置为从数据存储区中检索的锁定标识符,并返回 null。这将导致SessionStateModule 隔半秒后再次调用GetItemExclusive 方法,以尝试检索会话项信息和获取对数据的锁定。如果 lockAge 输出参数的设置值超过ExecutionTimeout 值,SessionStateModule 将调用ReleaseItemExclusive 方法以清除对会话项数据的锁定,然后再次调用 GetItemExclusive 方法。

如果 regenerateExpiredSessionId 属性设置为 true,则 actionFlags 参数用于其 Cookieless 属性为 true 的会话。actionFlags 值设置为 InitializeItem (1) 则指示会话数据存储区中的项是需要初始化的新会话。通过调用CreateUninitializedItem 方法可以创建会话数据存储区中未初始化的项。如果会话数据存储区中的项已经初始化,则 actionFlags 参数设置为零。

如果提供程序支持无 Cookie 会话,请将 actionFlags 输出参数设置为当前项从会话数据存储区中返回的值。如果被请求的会话存储项的 actionFlags 参数值等于InitializeItem 枚举值 (1),则 GetItemExclusive 方法在设置 actionFlags out 参数之后应将数据存储区中的值设置为零。

GetItem 方法

除了不尝试锁定数据存储区中的会话项以外,此方法与GetItemExclusive 方法执行的操作相同。GetItem 方法在 EnableSessionState 属性设置为 ReadOnly 时调用。

SetAndReleaseItemExclusive 方法

采用当前请求的 HttpContext 实例、当前请求的SessionID 值、包含要存储的当前会话值的SessionStateStoreData 对象、当前请求的锁定标识符以及指示要存储的数据是属于新会话还是现有会话的值作为输入。

如果 newItem 参数为 true,则SetAndReleaseItemExclusive 方法使用提供的值将一个新项插入到数据存储区中。否则,数据存储区中的现有项使用提供的值进行更新,并释放对数据的任何锁定。请注意,只有与提供的 SessionID 值和锁定标识符值匹配的当前应用程序的会话数据才会更新。

调用 SetAndReleaseItemExclusive 方法后,SessionStateModule 调用 ResetItemTimeout 方法来更新会话项数据的过期日期和时间。

ReleaseItemExclusive 方法

采用当前请求的 HttpContext 实例、当前请求的SessionID 值以及当前请求的锁定标识符作为输入,并释放对会话数据存储区中的项的锁定。在调用 GetItemGetItemExclusive 方法,并且数据存储区指定被请求项已锁定,但锁定时间已超过 ExecutionTimeout 值时会调用此方法。此方法清除锁定,释放该被请求项以供其他请求使用。

RemoveItem 方法

此方法在 Abandon 方法被调用时调用。

CreateUninitializedItem 方法

采用当前请求的 HttpContext 实例、当前请求的SessionID 值以及当前请求的锁定标识符作为输入,并向会话数据存储区添加一个 actionFlags 值为InitializeItem 的未初始化项。

如果 regenerateExpiredSessionId 属性设置为 true,则 CreateUninitializedItem 方法用于无 Cookie 会话,这将导致遇到过期会话 ID 时,SessionStateModule 会生成一个新的 SessionID值。

生成新的 SessionID 值的过程需要浏览器重定向到包含新生成的会话 ID 的 URL。在包含过期的会话 ID 的初始请求期间,会调用 CreateUninitializedItem 方法。SessionStateModule 获取一个新的 SessionID 值来替换过期的会话 ID 之后,它会调用CreateUninitializedItem 方法以将一个未初始化项添加到会话状态数据存储区中。然后,浏览器重定向到包含新生成的 SessionID 值的 URL。如果会话数据存储区中存在未初始化项,则可以确保包含新生成的 SessionID 值的重定向请求被视为新的会话,而不会被误认为是对过期会话的请求。

会话数据存储区中未初始化的项与新生成的 SessionID值关联,并且仅包含默认值,其中包括到期日期和时间以及与 GetItemGetItemExclusive 方法的actionFlags 参数相对应的值。会话状态存储区中的未初始化项应包含一个与 InitializeItem 枚举值 (1) 相等的actionFlags 值。此值由 GetItemGetItemExclusive 方法传递给SessionStateModule,并针对 SessionStateModule指定当前会话是新会话。然后,SessionStateModule将初始化该新会话,并引发 Session_OnStart 事件。

CreateNewStoreData 方法

采用当前请求的 HttpContext 实例和当前会话的Timeout 值作为输入,并返回带有空ISessionStateItemCollection 对象的新的SessionStateStoreData 对象、一个HttpStaticObjectsCollection 集合和指定的 Timeout值。使用 GetSessionStaticObjects 方法可以检索 ASP.NET 应用程序的 HttpStaticObjectsCollection 实例。

上面的定义有点长,其实很多都在说明一点那就是原生了Session是单线程的方式实现的,当多个进行读的时候会加锁后面的会等待。我们下面实现的去掉了这些锁,加快并发读写。

实现自己的RedisSessionStateStore

继承SessionStateStoreProviderBase实现自己的RedisSessionStateStore也很简单,只需继承SessionStateStoreProviderBase重写CreateNewStoreData,CreateUninitializedItem,GetItem等几个方法即可,下面贴出代码,参考InProcSessionStateStore实现。

使用也很简单,修改web.config

然后可以保持原先代码不变,像Session["UserCode"]="admin"方式进行使用,但是现在的Session已经具备了分布式的特征,支持跨域。这里得说一下该方式的缺点,在GetItem和SetAndReleaseItemExclusive时需要对键值对进行反序列化和序列化操作,对于保存数据量大的情况反而性能相对于系统提供的方式大打折扣,所以使用的时候需要考虑自己的实际场景。

上述内容就是分布式中Redis是怎样实现Session,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI