分布式中Redis是怎样实现Session

本篇文章为大家展示了分布式中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,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注创新互联行业资讯频道。


分享名称:分布式中Redis是怎样实现Session
转载来源:http://scyanting.com/article/pesgsg.html