【问题标题】:Using 'HttpContext.Current.Cache' safely安全地使用“HttpContext.Current.Cache”
【发布时间】:2010-04-14 14:47:44
【问题描述】:

我在这样的网络服务方法中使用Cache

var pblDataList = (List<blabla>)HttpContext.Current.Cache.Get("pblDataList");

if (pblDataList == null)
{
    var PBLData = dc.ExecuteQuery<blabla>(@"SELECT blabla");

    pblDataList = PBLData.ToList();

    HttpContext.Current.Cache.Add("pblDataList", pblDataList, null,
        DateTime.Now.Add(new TimeSpan(0, 0, 15)),
        Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
}

但我想知道,这段代码是线程安全的吗? Web 服务方法被多个请求者调用。在缓存为空的同时,不止一个请求者可能会尝试检索数据并添加到Cache

查询需要 5 到 8 秒。围绕此代码引入锁定语句会防止任何可能的冲突吗? (我知道可以同时运行多个查询,但我想确保一次只运行一个查询。)

【问题讨论】:

    标签: c# multithreading caching service thread-safety


    【解决方案1】:

    缓存对象是线程安全的HttpContext.Current 将无法从后台线程中获得。这可能适用于您,也可能不适用于您,从您的代码 sn-p 是否或不是您实际上正在使用后台线程,但如果您现在使用或决定在将来的某个时间点使用,请记住这一点。

    如果您可能需要从后台线程访问缓存,请改用HttpRuntime.Cache

    此外,虽然缓存上的单个操作是线程安全的,但顺序查找/存储操作显然不是原子的。您是否需要它们是原子的取决于您的特定应用程序。如果同一查询多次运行可能是一个严重的问题,即如果它产生的负载超过您的数据库能够处理的负载,或者如果请求返回的数据立即被覆盖在缓存,那么您可能希望在整个代码块周围加一个锁。

    但是,在大多数情况下,您真的想先进行分析,然后看看这是否真的是一个问题。大多数 Web 应用程序/服务不关心缓存的这一方面,因为它们是无状态的,而且缓存是否被覆盖也没关系。

    【讨论】:

    • 我不使用后台线程,它只是 Web 服务调用。顺便说一句,谢谢。
    【解决方案2】:

    你是对的。检索和添加操作不被视为原子事务。如果您需要防止查询多次运行,则需要使用锁。

    (通常这不是什么大问题,但在长时间运行的查询的情况下,它可能有助于减轻数据库的压力。)

    【讨论】:

    • 这真的取决于。在高吞吐量环境中,数据库上的额外负载可能没有这种锁定导致的请求限制那么重要。在大多数案例中,我会说你是对的,但每个案例都必须单独评估。
    【解决方案3】:

    我相信 Add 应该是线程安全的 - 即如果 Add 使用相同的键被调用两次,它不会出错,但显然查询可能执行两次。

    然而,另一个问题是数据是线程安全的。不能保证每个List&lt;blabla&gt; 都是隔离的——这取决于缓存提供者。内存缓存提供程序直接存储对象,因此如果任何线程编辑数据(添加/删除/交换列表中的项目,或更改其中一项的属性),则存在冲突风险。但是,使用 serializing 提供程序应该没问题。当然,这就要求blabla 是可序列化的……

    【讨论】:

    • 你能分享一个链接来序列化你的缓存对象吗?我试图为过滤一些数据的网页屏幕缓存工作中的数据表。我被告知服务器负载会太多。你知道任何关于缓存和序列化以及服务器负载的文章吗?谷歌搜索时我找不到任何具体内容。
    • @kcbeard 首先,一旦缓存:不要变异 DataTable。现在已经解决了:数据有多大?多少行?
    • 从几百行到最多 5k 行不等。十几个具有 date-time、int 和 var-char 数据类型的列。常识告诉我不要使用视图状态,所以支持我。我假设每个应用程序实例只有几个用户会访问它,所以一开始我使用 Current.Session,然后它被提出服务器负载太多所以我认为 Current.Cache(应用程序范围)。我的意思是,一个足够灵活以处理所有过滤的存储过程可能是最好的方法。但无论哪种方式,我都想了解更多关于缓存安全、最佳实践、陷阱等的信息。
    • 我还没有找到一篇关于 current.session 和 current.cache 安全实践和陷阱的好文章。我在这里和那里发现了很多一次性的东西和共同的观点,不要缓存大数据,不要使用会话你很容易受到 SQL 重放攻击。我是一名初级开发人员,只是想在第一次就做好,并且已经知道工作场所会以他们最舒服的方式来做,而不是总是最好的方式。我也意识到每个人都知道该做什么和不该做什么。所以我很幸运能抽出时间为 Marc 提供建议。
    • 顺便说一句,我在上一份工作中使用了你的 Windows 服务安装程序类,所以谢谢 :)
    猜你喜欢
    • 2011-06-16
    • 1970-01-01
    • 2011-06-29
    • 2016-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多