ASP.net Cache丢失的问题诊断

1 业务需求

缓存来自数据库的数据,不用频繁到数据库中加载。

2 使用模型

添加一个类 MyCache,然后在里面添加静态属性字段:

    public static DataTable FolderData
    {
        get
        {
            string key = "FolderData";
            object o = HttpRuntime.Cache[key];
            if (o == null)
            {
                //从DB中加载数据
                o = LoadFromDB();
                //添加到缓存中(分钟过期)
                HttpRuntime.Cache.Insert(key, o, null,
                    System.Web.Caching.Cache.NoAbsoluteExpiration,
                    TimeSpan.FromMinutes(30));
            }
            return (DataTable)o;
        }
    }

逻辑是取数据时如果没有,则去数据库中加载,然后添加到缓存中以便下次使用。

前台调用时直接用MyCache. FolderData即可。

3 运行的问题

运行一段时间后,通过后台数据库的监控,发现有一台Web服务器还是有多次加载的SQL发送到数据库的情况,而且发生的还很频繁。为什么缓存没有生效呢?丢了?添加监控日志:

    public static DataTable FolderData
    {
        get
        {
            string key = "FolderData";
            object o = HttpRuntime.Cache[key];
            if (o == null)
            {
                //从DB中加载数据
                o = LoadFromDB();
                saveLog("Add to Cache Key:" + key);
                //添加到缓存中(分钟过期)(指定回调函数)
                HttpRuntime.Cache.Insert(key, o, null,
                System.Web.Caching.Cache.NoAbsoluteExpiration,
                TimeSpan.FromMinutes(30),
                CacheItemPriority.Normal, ASPCacheRemoveCallBack);
            }
            return (DataTable)o;
        }
    }

A 添加进入Cache时,记录日志。

B 添加删除的回调函数,当缓存被删除时,记录日志。

    private static void ASPCacheRemoveCallBack
    (string key, object value, CacheItemRemovedReason reason)
    {
        saveLog("Key:" + key + "被删除,原因:" + reason + ",时间:" + DateTime.Now.ToString());
    }

然后分析这些日志,发现缓存有多次被删除,删除的原因是UnderUsed。

// 摘要:

// 之所以从缓存中移除该项,是因为系统要通过移除该项来释放内存。

Underused = 3,

但是连上服务器看,实际内存还有很多。(系统一共16G,使用的才11.5G,而且w3wp.exe进程才占用500MB。

为什么还有很多内存剩余,但是却说内存不够要把缓存的数据清理掉呢?因为是缓存,目的是少去数据库,缓存的东西如果多了,占用内存大了,OS不是还有虚拟内存吗?可以交换到硬盘呀,当然,如果这种情况发生,我们就把缓存的过期时间设小一点,少缓存点数据,维持系统平衡。但是不能还剩下4~5G的时候就不缓存了呀。

添加可用的日志:

    private static void ASPCacheRemoveCallBack
    (string key, object value, CacheItemRemovedReason reason)
    {
        saveLog("Key:" + key + "被删除,原因:" + reason + ",时间:" + DateTime.Now.ToString()
        + "可用数:" + HttpRuntime.Cache.EffectivePrivateBytesLimit);
    }

查看日志,发现EffectivePrivateBytesLimit的值是0.

查阅资料:

http://msdn.microsoft.com/zh-SG/library/system.web.caching.cache.effectiveprivatebyteslimit(v=vs.80)

EffectivePrivateBytesLimit 属性返回应用程序进程可使用的千字节数。达到此限制后,缓存算法开始积极清理缓存。

可使用应用程序配置文件中的 caching的 cache 元素(ASP.NET 设置架构) 元素的 privateBytesLimit 属性 (Attribute) 设置 EffectivePrivateBytesLimit 属性 (Property)。未设置 privateBytesLimit 属性时,缓存算法将确定缓存的最大大小,EffectivePrivateBytesLimit 属性将包含该算法所选择的大小。

为0表示ASP.net 认为没有可分配的内存了吗?实际情况并不是这样,系统刚运行一个缓存也没有时,它也是输出0。

进一步查看Web.Config,我们并没有设定privateBytesLimit属性的值。

IIS上设定了最大内存限制吗?

也没有设定内存的限制,而且也没有设定要定时回收进程,这点可以从Application的变量没有重新初始化丢失得到验证。

同样的程序部署运行在另外好几套环境,EffectivePrivateBytesLimit的值也是0,但是它们没有频繁发生UnderUsed的情况。所以EffectivePrivateBytesLimit的值为0并不代表没有内存可用了,需要清理,反而更像没有对此属性做设定的意思。

那到底是什么原因引起的ASP.net 的清理内存呢?

继续查阅资料:http://msdn.microsoft.com/zh-cn/library/ms228248%28v=vs.100%29.aspx

发现可以有几个设定来控制缓存的设定:

根据实际运行情况, 我们猜想:ASP.net 面临内存压力时好像算错了,好吧,我们让它不要算了,只要清理过期的数据就好了。把disableMemoryCollection设定为true,告诉ASP.net面临内存压力时不要回收内存。

连续运行3天,ASP.net 正常清理过期的数据,但是没有再出现删除原因为UnderUsed的日志,内存占用也稳定,没有大的波动。

4 结语

本来还想继续深入寻找ASP.net Cache的缓存的清理内存机制到底是什么,到底为什么出问题,初步反射了下它的代码,没有准确找到,再说这个问题是 MS搞出来的,负责人应该是它,不应该我们帮它排错(哈哈,偷懒的借口,不过每个人的精力是有限的,要解决回答为什么的问题是无限的。。。)

本文最终的结论就是设定了一个配置值而已,这么小的事似乎没必要发Blog,但是发现大批提到UnderUsed和disableMemoryCollection的文章都只有1句话的解释,没有详细的分析排错的过程,故而献丑写一篇,如有不对,还请大家指出,谢谢!

时间: 2024-10-31 08:37:08

ASP.net Cache丢失的问题诊断的相关文章

细说 ASP.NET Cache 及其高级用法

许多做过程序性能优化的人,或者关注过程程序性能的人,应该都使用过各类缓存技术. 而我今天所说的Cache是专指ASP.NET的Cache,我们可以使用HttpRuntime.Cache访问到的那个Cache,而不是其它的缓存技术. 以前我在[我心目中的Asp.net核心对象] 这篇博客中简单地提过它,今天我打算为它写篇专题博客,专门来谈谈它,因为它实在是太重要了.在这篇博客中, 我不仅要介绍它的一些常见用法,还将介绍它的一些高级用法. 在上篇博客[在.net中读写config文件的各种方法] 的

细说 ASP.NET Cache 及其高级用法【转】

阅读目录 开始 Cache的基本用途 Cache的定义 Cache常见用法 Cache类的特点 缓存项的过期时间 缓存项的依赖关系 - 依赖其它缓存项 缓存项的依赖关系 - 文件依赖 缓存项的移除优先级 缓存项的移除通知 巧用缓存项的移除通知 实现[延迟操作] 巧用缓存项的移除通知 实现[自动加载配置文件] 文件监视技术的选择 各种缓存方案的共存 许多做过程序性能优化的人,或者关注过程程序性能的人,应该都使用过各类缓存技术. 而我今天所说的Cache是专指ASP.NET的Cache,我们可以使用

asp.net session丢失的解决方法小结

现在我就把原因和解决办法写出来. ASP.NET Session丢失原因: 由于Asp.net程序是默认配置,所以Web.Config文件中关于Session的设定如下: < sessionState mode='InProc' stateConnectionString='tcpip=127.0.0.1:42424' sqlConnectionString='data source=127.0.0.1;Trusted_Connection=yes' cookieless='true' time

Asp.Net Cache辅助类

辅助类代码 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Caching; namespace BusinessRules.Common { /// <summary> /// Cache高度缓存 /// </summary> public class CacheManager { #region --Property-- p

asp.net Cache

因微信分享功能,获取access_token(一个toke 套一个token,7200秒过期时间)所以用到了asp.net Cache ,暂时发现Cache是最好用的,可以设置缓存自动过期时间,不说了 直接上代码...就一两行代码....,暂时记下来,方便以后快速回忆代码... //获取缓存 object cacheaccess_token = Cache.Get("access_token"); //添加缓存 Cache.Insert("access_token"

ASP.NET Cache缓存的使用

ASP.NET Cache是提升系统性能的重要方法,它使用了“最近使用”原则(a least-recently-used algorithm).在数据库访问中经常会用到Cache保存数据库数据. 1.缓存的添加: Cache的添加方法有Add()或Insert(),两种方法几乎类似,只是Inser方法可以使用可选参数,即使用默认参数,来实现缓存的添加: Cache.Add( KeyName,//缓存名 KeyValue,//要缓存的对象 Dependencies,//依赖项 AbsoluteEx

ASP.NET Cache的一些总结分享

最近我们的系统面临着严峻性能瓶颈问题,这是由于访问量增加,客户端在同一时间请求增加,这迫使我们要从两个方面解决这一问题,增加硬件和提高系统的性能. 1.1.1 摘要 最近我们的系统面临着严峻性能瓶颈问题,这是由于访问量增加,客户端在同一时间请求增加,这迫使我们要从两个方面解决这一问题,增加硬件和提高系统的性能. 大家可以通过各种各样的方法去优化我们系统,本篇博文将介绍通过Cache方法来优化系统的性能,减轻系统的负担. 1.1.2 正文 不同位置的缓存 在Web应用程序中的使用缓存位置主要有:客

ASP.NET Session丢失的解决方案

正常操作情况下会有ASP.NET Session丢失的情况出现.因为程序是在不停的被操作,排除Session超时的可能.另外,Session超时时间被设定成60分钟,不会这么快就超时的.现在我就把原因和解决办法写出来.ASP.NET Session丢失原因:由于Asp.net程序是默认配置,所以Web.Config文件中关于Session的设定如下:<sessionState mode='InProc' stateConnectionString='tcpip=127.0.0.1:42424'

ASP.NET cache缓存的用法

本文导读:在.NET运用中经常用到缓存(Cache)对象.有HttpContext.Current.Cache以及HttpRuntime.Cache,HttpRuntime.Cache是应用程序级别的,而HttpContext.Current.Cache是针对当前WEB上下文定义的.HttpRuntime下的除了WEB中可以使用外,非WEB程序也可以使用. 1.HttpRuntime.Cache 相当于就是一个缓存具体实现类,这个类虽然被放在了 System.Web 命名空间下了.但是非 Web