高流量网站的缓存函数是否线程安全/死锁安全?

4
下面的函数对于访问量较高的网站是否是一个好的实践?死锁或线程安全问题有什么缺点吗?
public static T GetInitializedTempCache<T>(string key, Func<T> getData, int minutes, bool skip = false)
{
    if (!skip)
    {
        var value = HttpRuntime.Cache[key];
        if (value == null || value.GetType() != typeof(T))
        {
            T data = getData();
            if (data != null && Config.Debugging.EnableCaching)
            {
                HttpRuntime.Cache.Add(key, data, null, DateTime.Now.AddMinutes(minutes), TimeSpan.Zero, System.Web.Caching.CacheItemPriority.Default, null);
            }
            return data;
        }
        return (T)value;
    }
    else
    {
        return getData();
    }
}

public static void RemoveTempCacheContains(string key)
{
    var keys = new List<string>();

    var enumerator = HttpRuntime.Cache.GetEnumerator();

    // copy all keys that currently exist in Cache
    while (enumerator.MoveNext())
    {
        var cacheKey = (string)enumerator.Key;

        if (cacheKey.Contains(key))
        {
            keys.Add(cacheKey);
        }
    }

    for (int i = 0; i < keys.Count; i++)
    {
        HttpRuntime.Cache.Remove(keys[i]);
    }
}

如果您正在考虑缓存,请查看 https://github.com/App-vNext/Polly 项目,这是一个“弹性和瞬态故障处理库”。它可能会在网站的其他领域为您提供帮助。 - user1378730
1个回答

2
回答你有关高流量网站的最佳实践的问题。是的,缓存长时间运行的IO请求是一个好的做法,并且使缓存机制通用也是一个好的做法。但有两个建议,将add更改为insert,因为您肯定会遇到竞争条件。 insert将始终插入最新的,而add则始终添加第一个。其次,由于您提到了高流量,请考虑使用异步函数替代方案。异步将允许长时间运行的IO函数不阻塞请求线程。
回答你的缺点问题。在此代码中,您没有使用任何锁,因此不应遇到任何死锁。我想getData()也没有任何锁,只是做一些长时间运行的IO操作。HttpRuntime.Cache也是线程安全的。因此,除非getData()不是线程安全的或具有锁定,否则这应该没问题。

1
这并没有对问题提供答案。如果想批评或要求作者澄清,请在他们的帖子下留言。- [来自审查] (/review/low-quality-posts/19591255) - Gerhard
2
@GerhardBarnard,这怎么没有回答他的问题?我指出了他的代码没有任何缺点,正如他所问的那样。并且,正如他所要求的那样,我为高流量网站提供了建议。如果你能为他找到另一个问题需要我来回答,那我非常乐意倾听。 - ATerry
你认为这篇文章怎么样?https://pseudomuto.com/2012/02/efficient-thread-safe-caching-with-asp.net/ - Mike Flynn
@MikeFlynn 他把从缓存和数据库中检索数据看作是一种竞争条件。然而,如果你采用这种方法,同时有100,000个请求进来,那么你实际上会使等待每个请求验证是否应该从缓存而不是数据库获取数据的响应序列化。因此,如果你的DB请求需要10毫秒,而缓存只需要1毫秒,那么你最后一个请求将需要1毫秒进行第一次缓存检查,12毫秒进行第一次锁定,以及99,999 * 1毫秒进行每个后续锁定;总响应时间为110.001秒。我建议使用在请求时可用的数据源。 - ATerry
你是说我应该像他一样使用 lock 设置,还是这只是无关紧要的。 - Mike Flynn
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接