锁定将数据加载到缓存缓存、加载、数据

2023-09-07 16:30:58 作者:ご流浪青年﹌

我有一个web应用程序的辅助类,其中它做的事情是present常见的,不变的数据对象的静态属性。我加载这些对象如下:

I have a helper class in a web app, and among the things it does is to present common, unchanging data objects as static properties. I'm loading these object as below:

public static class MyWebHelper
{
    #region - Constants & Fields 
    private const string LocationCacheKey = "MyWebHelper_Locations";
    private static object LocationLoadLock = new object();
    private static MemoryCache m_SiteCache;
    #endregion

    #region - Properties 
    /// <summary>
    /// Gets the uneditable collection of locations.
    /// </summary>
    public static ReadOnlyCollection<Location> Locations
    {
        get
        {
            EnsureLocationsCache();
            return (ReadOnlyCollection<Location>)SiteCache[LocationCacheKey];
        }
    }

    /// <summary>
    /// Gets the MemoryCache object specific for my site cache.
    /// </summary>
    public static MemoryCache SiteCache
    {
        get
        {
            if (m_SiteCache == null)
            {
                m_SiteCache = new MemoryCache("MyWeb_SiteCache");
            }
            return m_SiteCache;
        }
    }
    #endregion

    #region - Methods 
    private static void EnsureLocationsCache()
    {
        lock (LocationLoadLock)
        {
            if (SiteCache[LocationCacheKey] == null)
            {
                //
                // Load all Locations from the database and perform default sorting on location code.
                //
                List<Location> lLocations = DataAccess.GetAllLocations();
                lLocations.Sort(delegate(Location l1, Location l2) { return string.CompareOrdinal(l1.Code, l2.Code); });
                SiteCache[LocationCacheKey] = new ReadOnlyCollection<Location>(lLocations);
            }
        }
    }
    #endregion
}

我的问题是,是否锁定什么帮助?我想,以减少对数据库的调用,但在锁定刚刚引进的开销?缓存的数据用于pretty的常用整个网站,几乎不会改变。另外,我是锁定在正确的地方?

My question is, does the locking help anything? I'm trying to reduce calls to the database, but is the locking just introducing overhead? The cached data is used pretty commonly throughout the site, and will almost never change. Also, am I locking in the right place?

推荐答案

由于每个Web请求到服务器创建一个新的线程,静态辅助函数在这些线程共享的,某种类型的锁是有用的。如果没有锁,你会冒着进入EnsureLocationsCache方法,同时读取数据库已经在处理。现在,这可能不会影响两次的加载的数据的正确性,但如果在DB读出是昂贵它会影响整体性能和否定缓存的效果。

Since each web request to the server is creating a new thread, and your static helper is shared across these threads, a lock of some type is useful. Without a lock, you would be risking an entry into the EnsureLocationsCache method while a database read was already in process. Now this may not affect the correctness of the twice-loaded data but if the DB read is expensive it will impact your overall performance and negate the effect of caching.

这是真的取决于尝试访问EnsureLocationsCache()方法的应用程序的开始,这很可能是低并发线程的卷上,因为它是一次性的号召每个LocationCacheKey。

This is really dependant on the volume of concurrent threads trying to access the EnsureLocationsCache() method an application start, which is likely to be low as it's a one-time call for each LocationCacheKey.

获取锁的开销是一个有效的关注作为code获取即使当高速缓存已加载的锁。 @asawyer,@TomTom和@Joe已经提出了一些替代品。

The overhead of acquiring the lock is a valid concern as the code acquires a lock even when the cache has already been loaded. @asawyer, @TomTom and @Joe have suggested some alternatives.

编辑:

考虑调用EnsureLocationsCache()在 静态构造函数 。在这种情况下,你不应该在所有需要的锁。

Consider calling EnsureLocationsCache() in a static constructor. In this case you should not require a lock at all.

查看的静态构造函数的线程安全的讨论