缓存先前搜索的策略 (ASP.NET)
我有一个 ASP.NET MVC 2 Web 应用程序(.NET 4,C#),用户可以在其中搜索位置。
该页面是通过自动完成框实现的,与许多网站类似。 (Google、YouTube 等)
现在,对服务器的 AJAX 调用将导致对数据库的存储过程调用。 (虽然高效,但对于慢打字者来说可能会导致大量往返)。
我想知道如何创建一个策略来缓存最近 100 次搜索的结果?
我无法使用 OutputCache,因为调用是通过客户端上的 AJAX 进行的。我需要缓存存储过程的输出(查询文本的匹配位置列表)。
换句话说,很多人会搜索“纽约”或“旧金山”,而这些数据只能通过手动管理更改来更改(例如,我们可以手动使缓存无效)。
那么,如何缓存最近 100 个搜索呢?我希望有一个类似 FIFO 的功能,如果缓存已经有 100 次搜索,最旧的搜索就会被丢弃,所有内容都会向下移动。
我希望代码是这样的:
public ICollection<MatchedLocation> FindLocations(string queryText)
{
// Check last 100 searches.. How?
string cacheKey = queryText;
var matchedLocations = cachedPersistence.Get(cacheKey);
if (matchedLocations == null)
{
// Call db
matchedLocations = dbPersistence.GetLocations(queryText);
// Add to cache
cachedPersistence.Add(cacheKey, matchedLocations);
}
else
{
// Found in Cache! Awesome!
return matchedLocations;
}
}
我认为明显的选择是 .NET 队列?
但我以前从未使用过,所以有什么建议吗?我将如何实现获取/设置的并发性,我需要使用完全锁定的单例吗?有人为此目的使用过队列吗?我们还有什么其他选择?我几乎需要一个自定义队列来限制堆栈中的项目数量。
感谢您的帮助。
I have an ASP.NET MVC 2 Web Application (.NET 4, C#), where user's can search for locations.
The page is implemented with an auto-complete box, similar to many websites. (Google, YouTube, etc)
Now, the AJAX call to the server results in a Stored Procedure call to the database. (whilst efficient, could result in a lot of round-trips for slow typers).
I'm wondering how i can create a strategy to cache the result of say the last 100 searches?
I can't use OutputCache, as the call is made via AJAX on the client-side. I need to cache the output of the stored procedure (list of matched locations for a querytext).
In other words, a lot of people will search for "New York", or "San Francisco", and this data only changes via a manual admin change (where we could invalidate the cache manually, for example).
So, how could i cache the last 100 searches? I was hoping for a FIFO-like functionality, where if the cache already had 100 searches, the oldest one gets thrown away and everything get's moved down.
I want the code to be something like this:
public ICollection<MatchedLocation> FindLocations(string queryText)
{
// Check last 100 searches.. How?
string cacheKey = queryText;
var matchedLocations = cachedPersistence.Get(cacheKey);
if (matchedLocations == null)
{
// Call db
matchedLocations = dbPersistence.GetLocations(queryText);
// Add to cache
cachedPersistence.Add(cacheKey, matchedLocations);
}
else
{
// Found in Cache! Awesome!
return matchedLocations;
}
}
I'm thinking the obvious choice would be a .NET Queue?
But i've never used that before, so any advice? How would i implement concurrency for the get/set, Would i need to use a fully-locked Singleton? Has anyone used a Queue for this purpose? What other options do we have? I would almost need a custom queue, to limit the number of items in the stack.
Thanks for your help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您只想缓存 100 个,您可以使用带有上次使用时间的相应字典的字典。您可以使用读写锁来代替允许多个读取器的完整锁。
使用下面的代码,两个线程可能可以输入
EnterWriteLock
以获得相同的值。惩罚将是两次数据库调用,这可能不是问题。您可以通过执行另一个TryGetValue
并在必要时锁定(双重锁定)来避免这种情况。If you only want to cache a 100 you could use a Dictionary with a corresponding Dictionary with last used times. And you can use a reader writer lock instead of a full blown lock which allows multiple readers.
With the code below potentially two threads can enter
EnterWriteLock
for the same value. The penalty would be two db calls which might not be an issue. You can avoid this by doing anotherTryGetValue
and locking (double locking) if necessary.