• 网站性能优化之应用程序缓存初篇


    一. 摘要

          首先声明这篇服务器缓存篇是我平时工作中的一些经验心得,对没有用过,或者不知道如何使用服务器缓存的朋友们提供一个简单的认识与实现思路,本文只是抛

    砖引玉,还请各位多多提出宝贵意见,希望能够在大家的指导下写出更好的经验总结,为更多的不会使用或者不知道如何下手的朋友们提供帮助。

          闲话,之前写的部分文章可能条理性也不是特别清楚,特别参考博客园部分大牛的组织形式来书写,通过清晰的文章结构,不但能让自己写文章的时候思路清晰,

    更能为看到这篇文章的朋友理解我讲解的目的,这就是最好的结果啦。

          本人主要讲解的内容:通过程序代码来实现ASP.NET网站的缓存功能。

    二. 本文提纲

    · 1.摘要

    · 2.本文提纲

    · 3.服务器缓存简介

    · 4.准备工作

    · 5.第一个简单程序

    · 6.程序配置与部署

    · 7.本文总结

    三. 服务器缓存简介

        缓存的优势:
        缓存是一种无需大量时间和分析就可以获得"足够良好的"性能的方法。这里再次强调,内存现在非常便宜,因此,如果您能通过将输出缓存 30 秒,
    而不是花上一整天甚至一周的时间尝试优化代码或数据库就可以获得所需的性能,您肯定会选择缓存解决方案(假设可以接受 30 秒的旧数据)。
    缓存正是那些利用 20% 付出获得 80% 回报的特性之一,因此,要提高性能,应该首先想到缓存。不过,如果设计很糟糕,
    最终却有可能带来不良的后果,因此,您当然也应该尽量正确地设计应用程序。但如果您只是需要立即获得足够高的性能,缓存就是您的最佳选择,
    您可以在以后有时间的时候再尽快重新设计应用程序。 
        缓存的使用原则:
        尽早缓存;经常缓存 
    
         您应该在应用程序的每一层都实现缓存。向数据层、业务逻辑层、UI 或输出层添加缓存支持。
        内存现在非常便宜 — 因此,通过以智能的方式在整个应用程序中实现缓存,可以获得很大的性能提高。
        缓存的过期策略在缓存部署后也将将起到决定性的作用。
     
        通过上面的介绍我们已经找到了缓存的重要性,所以我们在做性能优化时能用缓存的时候,尽量用缓存吧。
    应用程序数据缓存

          应用程序数据缓存提供了一种编程方式,可通过键/值对将任意数据存储在内存中。使用应用程序缓存与使用应用程序状态类似。但是,与应用程序状态不同的是,

    应用程序数据缓存中的数据是易失的,即数据并不是在整个应用程序生命周期中都存储在内存中。应用程序数据缓存的优点是由ASP.NET管理缓存,它会在项过期、无

    效,或内存不足时移除缓存中的项,还可以配置应用程序缓存,以便在移除项时通知应用程序。

    四. 准备工作

          既然要使用缓存,我们首先要知道ASP.NET开发中VS平台可给我提供了什么样的方法去实现这个缓存服务,首先给大家介绍的就是System.Web.Caching.Cache类,这个类负责Web服务器中缓存的管理。

          我们先来看看这个类下的相关成员及每个成员的工作是什么?
    
           //获取缓存集合中的总数 
    
           public int Count
           {
               get;
           }
    
           //这个属性用来查看缓存服务在服务器中可用的物理内存的百分比
    
          public long EffectivePercentagePhysicalMemoryLimit
          {
              get;
          }
    
          //获取或设置缓存对象
    
           public object this[string key]
            {
                get;
                set;
            } 
    
           public object Add(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback); 
    
         //检索到的缓存项,未找到该键时为 null。       
    
         public object Get(string key); 
    
         //返回一个可枚举的集合 
    
         public IDictionaryEnumerator GetEnumerator(); 
    
         public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemUpdateCallback onUpdateCallback);
         public void Insert(string key, object value, CacheDependency dependencies, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback); 
    
    

    五. 第一个简单程序

          程序中可以写一个单独的CacheHelper包装相应的缓存方法,通过在程序中调用缓存,来实现相应的优化目的,

          首先这个类中的所有成员是静态成员,这样可以不用创建对象

             /// <summary>
            /// 初始化服务器缓存
            /// </summary>
            private static System.Web.Caching.Cache cache = HttpRuntime.Cache;//这里是默认取当前应用程序的服务缓存。 
    
            
    
           /// <summary>
           /// 返回指定的缓存信息
           /// </summary>
           /// <param name="key">键</param>
           /// <returns>缓存信息</returns>
           public static object Get(string key)
           {
               return cache[key];
           } 
    
           
    
            /// <summary>
            /// 删除指定键的缓存
            /// </summary>
            /// <param name="key">键</param>
            /// <returns>缓存信息</returns>
            public static bool Remove(string key)
            {
                return !(null==cache.Remove(key));
            } 
    
            /// <summary>
            /// 添加缓存信息
            /// </summary>
            /// <param name="key">键</param>
            /// <param name="value">要缓存的信息</param>
            public static void Set(string key, object value)
            {
                cache.Insert(key, value,null,System.Web.Caching.Cache.NoAbsoluteExpiration,TimeSpan.FromMinutes(3));
            } 
    
            
    
            /// <summary>
           /// 判定是否存在知道键的缓存信息
           /// </summary>
           /// <param name="key">键</param>
           /// <returns>是否存在</returns>
           public static bool Exist(string key)
           {
               return !(null == cache[key]);
           } 
    
           /// <summary>
           /// 添加缓存信息
           /// </summary>
           /// <param name="key">键</param>
           /// <param name="value">要缓存的信息</param>
           /// <param name="datetime">过期时间</param>
           public static void Set(string key, object value,DateTime datetime)
           {
               cache.Insert(key, value, null,datetime,System.Web.Caching.Cache.NoSlidingExpiration);
           } 
    
           /// <summary>
           /// 添加缓存信息
           /// </summary>
           /// <param name="key">键</param>
           /// <param name="value">值</param>
           /// <param name="swcc">缓存对象的依赖关系</param>
           public static void Set(string key, object value, System.Web.Caching.CacheDependency swcc)
           {
               cache.Insert(key, value, swcc, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(3), System.Web.Caching.CacheItemPriority.Default, null);
           }
    
    

           具体的缓存读取修改代码如下:

             //定义一个泛型集合用来保存相应的实体,或者是datatable都是可以的。 
    
           private static Dictionary<int, EasyStore.Model.Product.Productclass> productClass = new Dictionary<int, EasyStore.Model.Product.Productclass>(); 
    
            /// <summary>
            /// 获取产品分类名称
            /// </summary>
            /// <param name="cid">产品分类ID</param>
            /// <returns>产品分类名称</returns>
            public static string GetProductClassName(int cid)
            {
                string className = string.Empty; 
    
                //判定缓存中是否存在指定键的缓存对象 
    
                if (!CacheHelper.Exist(productClass.GetHashCode().ToString()))
                {
                    EasyStore.BLL.Product.Productclass cBll = new EasyStore.BLL.Product.Productclass();
                    List<EasyStore.Model.Product.Productclass> models = cBll.GetAll();
                    foreach (EasyStore.Model.Product.Productclass model in models)
                    {
                        if (!productClass.ContainsKey(model.ID))
    
                            //将实体添加到缓存列表中
                            productClass.Add(model.ID, model);
                    } 
    
                    //缓存存储实体的集合对象
    
                    CacheHelper.Set(productClass.GetHashCode().ToString(), productClass);
                }
                else
                {
    
                    ////判定缓存中是否存在指定键的缓存对象,存在则直接从缓存中取出指定键的对象,并强制转换为指定实体集合对象。
                    productClass = CacheHelper.Get(productClass.GetHashCode().ToString()) as Dictionary<int, EasyStore.Model.Product.Productclass>;
                } 
    
                //其他操作。
    
                className = productClass.ContainsKey(cid) ? productClass[cid].Name : string.Empty; 
    
                return className;
            }
    
    

      业务代码中的调用

            上面大概给出了缓存的相关代码,其他的代码都类似。

             //将缓存中指定的键的缓存对象取出 
    
            DataTable dt = CacheHelper.Get("DBES_PRODUCTCLASS") as DataTable; 
    
            //其他业务代码 
    
            if (drs != null && drs.Length > 0)
                {
                    foreach (DataRow row in drs)
                    {
                       //TODO..
    
                    }
                }
    
    

    六. 程序配置与部署

           简单的应用程序缓存服务,基本上不需要太多的配置与部署,分布式服务缓存则会在这方面很重要,接下来的高级篇将会介绍到这个服务的具体应用,还将讲解如

    何构建高性能的分布式访问缓存服务器。

    七. 本文总结

        缓存可以使应用程序的性能得到很大的提高,因此在设计应用程序以及对应用程序进行性能测试时应该予以考虑。
        应用程序总会或多或少地受益于缓存,当然有些应用程序比其他应用程序更适合使用缓存。
        对 ASP.NET 提供的缓存选项的深刻理解是任何 ASP.NET 开发人员应该掌握的重要技巧。 

    结束语

          本文只是简单的说明如何通过应用程序的方式实现缓存,下一篇将如何在应用程序中使用缓存的策略和过期的策略如何设置,能更好的满足缓存的服务做更深入的

    说明,还希望大家在使用的过程中对我提出更好的意见和建议,小弟谢过!

  • CallHot

反馈文章质量,你可以通过快速通道评论:
  • 相关阅读:
    【漏洞复现】CVE2022–21661 WordPress核心框架WP_Query SQL注入漏洞原理分析与复现
    PAT顶级 1001 Battle Over Cities Hard Version (35 分)(最小生成树)
    Leetcode 1001. 网格照明(map)
    2022牛客寒假算法基础集训营4 ABCDEFGHIJK
    KD Tree 模版
    PAT顶级 1003 Universal Travel Sites (35 分)(DP)
    CCFCSP认证 2021123 登机牌条码(90分)
    Leetcode 956. 最高的广告牌(DP)
    Codeforces Round #774 (Div. 2) C. Factorials and Powers of Two(暴力/dfs/位运算)
    第 46 届 ICPC 国际大学生程序设计竞赛亚洲区域赛(上海)I. Steadily Growing Steam(DP)
  • 原文地址:https://www.cnblogs.com/hegezhou_hot/p/1822448.html
  • Copyright © 2020-2023  润新知