Redis 支持的 ASP.NET SessionState 提供程序 [关闭]
Posted
技术标签:
【中文标题】Redis 支持的 ASP.NET SessionState 提供程序 [关闭]【英文标题】:Redis backed ASP.NET SessionState provider [closed] 【发布时间】:2011-12-25 12:25:25 【问题描述】:我目前正在开发一个由 Redis 使用 Booksleeve 支持的 ASP.NET SessionState 自定义提供程序。 Redis 似乎非常适合 SessionState(如果您必须使用它),因为:
Redis 可以像 RDBMS 一样持久存储,但速度要快得多。 Key/Value 数据存储更适合 SessionState 的接口。 由于数据未存储在进程中(如默认的 Session 提供程序),SessionState 可以承受 Web 服务器重启、崩溃等情况。 如果需要,Redis 很容易水平分片。所以,我想知道这是否对任何人有用,因为我们(我的公司)正在考虑在 GitHub 上开源它。想法?
更新:
我昨天确实发布了第一个版本:https://github.com/angieslist/AL-Redis/blob/master/AngiesList.Redis/RedisSessionStateStore.cs
【问题讨论】:
会非常有用 - 事实上,我不久前就开始自己研究这个,所以我肯定会为这个项目做出很多贡献。我强烈建议如果你深入研究这个,你建立在 ServiceStack ICacheClient 接口之上。 Redis 是少数包含的缓存客户端之一,包括一个非常适合调试的进程内内存缓存。 如果对你有用,也会对其他人有用。去做吧。 到目前为止,我一直坚持使用 Booksleeve 作为 Redis 客户端库。我最初考虑使用 SS 的 ICacheClient,但我很快意识到 Redis 的哈希数据类型非常适合 SessionData。所以我需要一个较低级别的、特定于 Redis 的客户端。此外,由于我需要执行每个 HttpRequest 锁定以“正确”实现与内置 ASP.NET 会话提供程序相同的功能,因此我认为我应该更接近金属。然而,最终,我想让锁定成为可选/可配置的。 很惊讶这个问题没有立即关闭,因为 SO mods 没有建设性......(顺便说一句,伟大的项目想法) 我确实计划使用 ServiceStack.Text 为序列化提供一系列选择。我已经使用 SessionStateItemCollection.Deserialize/Serialize 获得了本机序列化。然后我可以使用 SS.Text 添加 JSON 和 JSV,以及一个要实现的接口,这样任何人都可以创建自己的自定义序列化程序。 【参考方案1】:我创建了一个基于 Redis 的 SessionStateStoreProvider
can be found on GitHub 使用 ServiceStatck.Redis
作为客户端(而不是 Booksleeve)。
它可以通过 NuGet 使用Install-Package Harbour.RedisSessionStateStore
安装。
我发现@NathanD 的方法有一些怪癖。在我的实现中,锁与 存储在会话值中,而不是存储在单独的键中(较少往返 Redis)。此外,因为它使用ServiceStack.Redis
,所以它可以使用池连接。
终于,它被测试了。这是我对@NathanD 方法的最大反感。如果不手动运行每个用例,就无法实际上知道它是否有效。
【讨论】:
您是否在具有相同会话 ID 的显着并发的环境中测试了会话存储?我很想知道您如何处理锁定,以及在负载很大的应用程序中使用 Redis 会话存储是否安全。 @RobertMircea - 我按照 MSDN 上的示例和最佳实践来实现 SessionStateStoreProviders。锁定的完成方式与 SQL 和 Azure 会话状态提供程序大致相同(因为它们都大致实现了 MSDN 中的相同示例)。对于您的问题 - 是的,我已经测试了几个负载很大的应用程序(即使对于相同的会话 ID)。我与提供商的问题为零。但是,如果您确实发现了问题,请告诉我并在 Github 上打开一个问题。 我唯一担心的是 Redis 不像数据库那样支持事务,在这种情况下,状态可以在两个 Redis 操作之间改变。我查看了代码,您似乎在 GetItem 中有这样的代码: var stateRaw = client.GetAllEntriesFromHashRaw(key); [用数据做一些事情] ...在 Redis 中保存更改...在从 Redis 读取操作和保存之间,可能会发生很多事情,而且我相信,您不能保证在 Redis 中找到与之前相同的会话状态数据初始读取的时刻... Redis 是会话状态的正确存储吗?至少不使用 Lua 原子脚本? @RobertMircea - 我现在明白你了。很好的收获。我在完全理解WATCH
之前写了这个。我做了一些改变。你介意看看issue #1 和associated code 吗?一旦你看过它,我会推送到 NuGet。谢谢!
VS StateServer模式有一些性能测试吗?【参考方案2】:
它不仅有用,而且我强烈认为如果您打算走这条路,请仔细查看 Redis 的 Hash 数据类型。在我们的应用程序中,会话基本上是键和值的小集合(即:user_id: 7, default_timezone: 'America/Chicago', ...
),整个用户会话存储在单个 Redis 哈希中。
如果您的会话数据相似,使用 Hash 不仅可以简化数据映射,而且 Redis 通过这种方法使用空间 much more efficiently。
我们的应用程序是 ruby,但您可能仍会从 what we wrote 找到一些用处。
【讨论】:
谢谢 Carl,是的,我正在使用哈希类型 - 非常合适。使用 Hash 的另一个优点是,如果我以后想要支持显式延迟或急切加载特定会话项的能力,它只是一个附加组件,而不是完全重写。 如果用户也有一个 cmets 列表,我还需要将其保存为 comment_id:1,Content:text1,comment_id:2,Content:text2.. 的哈希值还是可以将它们保存为 List以上是关于Redis 支持的 ASP.NET SessionState 提供程序 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
asp.net core 使用 Redis 和 Protobuf
RedisSessionStateProvider 支持redis集群吗