asp.net中Cache的并发访问问题
2010-07-21 15:07
162 查看
在asp.net中我们可以把我们的一些静态数据通过Cache来缓存,已提高网站性能。下面是msdn上一个使用Cache的例子。其中有可很意思的功能是
我们可以给缓存项指定一个回调,当缓存项被remove的时候将调用回调方法通知我们。我们公司的一个应用使用了这个方法用来缓存对数据库的一些更新,来避免频繁操作数据库已提高性能。当缓存被清除的时候在调用回调吧缓存的数据集中写入数据库。这种方法当并发访问量大大时候就会出现阻塞线程的问题。从而导致cpu狂涨。最后可能耗尽所有线程池线程。
代码<html>
<Script runat=server language="C#">
static bool itemRemoved = false;
static CacheItemRemovedReason reason;
CacheItemRemovedCallback onRemove = null;
public void RemovedCallback(String k, Object v, CacheItemRemovedReason r){
itemRemoved = true;
reason = r;
}
public void AddItemToCache(Object sender, EventArgs e) {
itemRemoved = false;
onRemove = new CacheItemRemovedCallback(this.RemovedCallback);
if (Cache["Key1"] == null)
Cache.Add("Key1", "Value 1", null, DateTime.Now.AddSeconds(60), TimeSpan.Zero, CacheItemPriority.High, onRemove);
}
public void RemoveItemFromCache(Object sender, EventArgs e) {
if(Cache["Key1"] != null)
Cache.Remove("Key1");
}
</Script>
<body>
<Form runat="server">
<input type=submit OnServerClick="AddItemToCache" value="Add Item To Cache" runat="server"/>
<input type=submit OnServerClick="RemoveItemFromCache" value="Remove Item From Cache" runat="server"/>
</Form>
<% if (itemRemoved) {
Response.Write("RemovedCallback event raised.");
Response.Write("<BR>");
Response.Write("Reason: <B>" + reason.ToString() + "</B>");
}
else {
Response.Write("Value of cache key: <B>" + Server.HtmlEncode(Cache["Key1"] as string) + "</B>");
}
%>
</body>
</html>原因是Cache其实是个全局对象,所以对Cache的访问都会在内部通过一个ReaderWriterLock进行同步。在Remove缓存项调用回调方法的时候,由于回调方法又访问数据库。结果导致Remove缓存项长时间的占用锁,导致其他请求无法读取写入缓存,从而阻塞线程池中其他线程。所以缓存项的回调方法不适合调用长时间的操作。最好是移除缓存项后,在自己调用后续操作。避免锁定争用。
我们可以给缓存项指定一个回调,当缓存项被remove的时候将调用回调方法通知我们。我们公司的一个应用使用了这个方法用来缓存对数据库的一些更新,来避免频繁操作数据库已提高性能。当缓存被清除的时候在调用回调吧缓存的数据集中写入数据库。这种方法当并发访问量大大时候就会出现阻塞线程的问题。从而导致cpu狂涨。最后可能耗尽所有线程池线程。
代码<html>
<Script runat=server language="C#">
static bool itemRemoved = false;
static CacheItemRemovedReason reason;
CacheItemRemovedCallback onRemove = null;
public void RemovedCallback(String k, Object v, CacheItemRemovedReason r){
itemRemoved = true;
reason = r;
}
public void AddItemToCache(Object sender, EventArgs e) {
itemRemoved = false;
onRemove = new CacheItemRemovedCallback(this.RemovedCallback);
if (Cache["Key1"] == null)
Cache.Add("Key1", "Value 1", null, DateTime.Now.AddSeconds(60), TimeSpan.Zero, CacheItemPriority.High, onRemove);
}
public void RemoveItemFromCache(Object sender, EventArgs e) {
if(Cache["Key1"] != null)
Cache.Remove("Key1");
}
</Script>
<body>
<Form runat="server">
<input type=submit OnServerClick="AddItemToCache" value="Add Item To Cache" runat="server"/>
<input type=submit OnServerClick="RemoveItemFromCache" value="Remove Item From Cache" runat="server"/>
</Form>
<% if (itemRemoved) {
Response.Write("RemovedCallback event raised.");
Response.Write("<BR>");
Response.Write("Reason: <B>" + reason.ToString() + "</B>");
}
else {
Response.Write("Value of cache key: <B>" + Server.HtmlEncode(Cache["Key1"] as string) + "</B>");
}
%>
</body>
</html>原因是Cache其实是个全局对象,所以对Cache的访问都会在内部通过一个ReaderWriterLock进行同步。在Remove缓存项调用回调方法的时候,由于回调方法又访问数据库。结果导致Remove缓存项长时间的占用锁,导致其他请求无法读取写入缓存,从而阻塞线程池中其他线程。所以缓存项的回调方法不适合调用长时间的操作。最好是移除缓存项后,在自己调用后续操作。避免锁定争用。
相关文章推荐
- 利用Memcache解决数据库高并发访问的瓶颈问题
- Spring-MVC并发访问的线程安全性问题
- memcached缓存失效时的高并发访问问题解决
- Springmvc 并发访问的线程安全性问题
- 使用redis解决一些并发访问的问题
- 事务并发访问问题
- memcache解决高并发高访问的数据库瓶颈问题
- 利用Memcache解决数据库高并发访问的瓶颈问题
- (转)Spring并发访问的线程安全性问题(高度总结)
- cocoa并发访问Sqlite中的死锁问题
- Windows环境下解决Nginx+php并发访问阻塞问题。
- Oracle 数据库中不同事务并发访问的问题
- 使用Spring4.3解决缓存过期后多线程并发访问数据库的问题
- 多进程同时访问文件并发问题解决方法
- 关于线程并发访问全局变量问题
- Spring 并发访问的线程安全性问题
- 高访问,高并发等大型网站架构常见问题汇总
- 避免客户端访问的并发问题
- web并发访问的问题
- SpringMVC和Struts2并发访问时的线程安全问题