我有一个 ASP.NET 站点,其搜索功能相当慢,我想通过使用查询作为缓存键将结果添加到缓存一小时来提高性能:
using System;
using System.Web;
using System.Web.Caching;
public class Search
{
private static object _cacheLock = new object();
public static string DoSearch(string query)
{
string results = "";
if (HttpContext.Current.Cache[query] == null)
{
lock (_cacheLock)
{
if (HttpContext.Current.Cache[query] == null)
{
results = GetResultsFromSlowDb(query);
HttpContext.Current.Cache.Add(query, results, null, DateTime.Now.AddHours(1), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
}
else
{
results = HttpContext.Current.Cache[query].ToString();
}
}
}
else
{
results = HttpContext.Current.Cache[query].ToString();
}
return results;
}
private static string GetResultsFromSlowDb(string query)
{
return "Hello World!";
}
}
假设访客 A 进行了搜索。缓存为空,设置锁并向数据库请求结果。现在,访问者 B 进行了不同的搜索:访问者 B 是否必须等待访问者 A 的搜索完成?我真正想要的是 B 立即调用数据库,因为结果会有所不同,并且数据库可以处理多个请求 - 我只是不想重复昂贵的不必要的查询。
对于这种情况,正确的方法是什么?
除非您绝对确定没有冗余查询至关重要,否则我会完全避免锁定。 ASP.NET 缓存本质上是线程安全的,因此以下代码的唯一缺点是,当关联的缓存条目过期时,您可能会暂时看到一些冗余查询相互竞争:
public static string DoSearch(string query)
{
var results = (string)HttpContext.Current.Cache[query];
if (results == null)
{
results = GetResultsFromSlowDb(query);
HttpContext.Current.Cache.Insert(query, results, null,
DateTime.Now.AddHours(1), Cache.NoSlidingExpiration);
}
return results;
}
如果您决定确实必须避免所有冗余查询,那么您可以使用一组更细粒度的锁,每个查询一个锁:
public static string DoSearch(string query)
{
var results = (string)HttpContext.Current.Cache[query];
if (results == null)
{
object miniLock = _miniLocks.GetOrAdd(query, k => new object());
lock (miniLock)
{
results = (string)HttpContext.Current.Cache[query];
if (results == null)
{
results = GetResultsFromSlowDb(query);
HttpContext.Current.Cache.Insert(query, results, null,
DateTime.Now.AddHours(1), Cache.NoSlidingExpiration);
}
object temp;
if (_miniLocks.TryGetValue(query, out temp) && (temp == miniLock))
_miniLocks.TryRemove(query);
}
}
return results;
}
private static readonly ConcurrentDictionary<string, object> _miniLocks =
new ConcurrentDictionary<string, object>();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)