【问题标题】:Implementing cache correctly in a class library for use in an asp.net application在类库中正确实现缓存以在 asp.net 应用程序中使用
【发布时间】:2010-09-14 11:07:26
【问题描述】:

我正在一个类库中实现一个缓存,该类库正在一个 asp.net 应用程序中使用。

我使用静态方法将缓存对象创建为单例模式来更新缓存,该方法实际上只是用我需要缓存的数据集合加载成员变量/属性(当然有一些锁定逻辑)。我认为这是一个不错的方法,因为我可以通过调用来访问我的数据

MyCacheObject.Instance.MyDataCollection

我正在创建一个新的缓存对象来存储由某个键分区的大量数据。我的意思是我正在创建一个新的缓存,但这个缓存不会一次加载所有数据,而是为每个访问的键存储一个集合。

MyOtherCacheObject.Instance.MyOtherDataCollection(indexkey)

这次提出了关于垃圾收集的问题。由于我正在存储大量数据,如果它突然被 gc'ed 会不会是一种浪费?由于它只是一个单例模式,因此无法确保数据会保留在缓存中。

所以我的问题是 - 实施缓存来处理这种情况的最佳做法是什么?我真的不喜欢一个非常复杂的解决方案,而且我知道 System.Web 中有缓存,但这似乎有点“离题”,因为这只是一个类库,或者你怎么看?

【问题讨论】:

    标签: c# asp.net caching garbage-collection singleton


    【解决方案1】:

    在我看来,最好的解决方案应具备以下特点:

    • 使用平台提供的可用缓存服务,尽量避免自己编写。

    • 不将您的类库耦合到 System.Web,以使层保持一致。

    • 但如果类库在 ASP.NET 应用程序中运行,则该解决方案不需要引入另一个缓存实现(例如,企业库缓存应用程序块),这需要额外的配置和设置。

    因此,我将使用 IoC 策略,以允许类库根据其运行环境使用不同的缓存实现。

    假设您将抽象缓存合约定义为:

    public interface ICacheService 
    {
        AddItem(...);
    }
    

    您可以提供基于 System.Web 的实现:

    public AspNetBasedCacheService : ICacheService
    {
        AddItem(...)
        {
            // Implementation that uses the HttpContext.Cache object
        }
     }
    

    然后将该实现“发布”为单例。请注意,与原始方法的不同之处在于,单例只是对基于 ASP.NET 缓存服务的实现的引用,而不是完整的“缓存对象”。

    public class CacheServiceProvider 
    {
        public static ICacheService Instance {get; set;}
    
    }
    

    您必须通过执行延迟初始化或在应用程序启动时(Global.asax.cs)来初始化缓存实现

    并且每个域组件都可以使用已发布的缓存服务,而无需知道它是基于 System.Web 实现的。

    // inside your class library:
    ICacheService cache = CacheServiceProvider.Instance;
    cache.AddItem(...);
    

    我同意这可能不是最简单的解决方案,但我的目标是在不牺牲代码解耦和灵活性的情况下利用 ASP.NET 缓存实现。

    希望我正确理解了您的问题。

    【讨论】:

    • 我喜欢你所得到的(尽管我会竭尽全力避免 IoC)。你提出了一些我可以运行的好主意。谢谢
    • 您还可以添加一个支持变量并在执行设置时对该变量执行锁定。我的直觉表明它可能会阻止一些线程问题。
    【解决方案2】:

    只要缓存仍然持有对数据的引用,数据就不会被垃圾回收。

    另外,永远不要使用单例。

    【讨论】:

    • 但我担心缓存对象会被 gc'ed 而不是它缓存的数据。
    • 也不是使用单例来保存我的缓存,还有什么更好的方法?
    • 为什么缓存对象会被垃圾回收?只要有对它的引用,就不会发生这种情况
    • “另外,永远不要使用单例。” - 单例仍然有合法用途,尤其是接口实现(因为你不能有静态接口)。
    • 我的意思是那个参考在哪里?该引用仅在 asp.net 页面请求期间存在。假设网站负载很重,一次可能至少有一个引用,但它不是一个用户非常多的网站,那么谁来保存引用?
    猜你喜欢
    • 1970-01-01
    • 2011-11-29
    • 1970-01-01
    • 2013-03-21
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    • 2011-07-26
    • 1970-01-01
    相关资源
    最近更新 更多