SPB-设计机制-缓存机制

来自站长百科
跳转至: 导航、​ 搜索

导航: 上一页

缓存用途

缓存是SPB中非常重要的一个临时存储,是提升性能的一个非常重要的设计机制。缓存的作用主要有如下几点:

  1. 缓存从数据库查询到的数据,减少与数据库的连接次数;
  2. 缓存从配置文件读取的数据,==减少==对文件系统的读写次数;
  3. 缓存依靠反射进行实例化的类的实例,减少反射的次数;
  4. 缓存View在某个皮肤中对应的aspx/ascx路径,减少View文件查找的时间;

缓存数据库中的数据是缓存在SpaceBuilder中最重要的用途。基本上所有数据都是在业务逻辑层首先在缓存中获取,如果找不到则从数据库中获取并缓存在内存中供下一次访问使用。SPB在提升性能的同时也必须考虑缓存与数据库实际数据的同步性,因此需要在增、删、改时手动使相应的缓存失效。

Spacebuilder089.jpg

使用规则

缓存使用示例代码:(获取SPBCacheManager)

SPBCacheFactory.GetCacheManager(string cacheManagerName);

如何使用缓存

  • 配置CacheManage

在web.config的<cacheManagers>节点配置cacheManager

<cacheManagers>

<add expirationPollFrequencyInSeconds="120" maximumElementsInCacheBeforeScavenging="1000000"

numberToRemoveWhenScavenging="10" backingStoreName="Null Storage"

type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching" 

name="Blog" />

</cacheManagers>
  • 获取SPBCacheManager
SPBCacheManager CacheManager = SPBCacheManagerFactory.GetCacheManager(“Blog”);

Spacebuilder090.jpg

过期策略

  • 绝对时间
CacheManager.Add(cacheKey, pds, SPBCacheManager.CachingExpirationType.ObjectCollection);

预定义的SPBCacheManager.CachingExpirationType包含以下几种类型:

Spacebuilder091.jpg

  • 文件依赖

一般对于配置文件的缓存采用文件依赖,即当配置文件发生变化后,缓存自动失效。例如:

string path = HttpContext.Current.Server.MapPath("~/SpaceBuilder.config");

config = new SPBConfig(path);

cacheManager.Add(cacheKey, config, path);
  • 手动过期

缓存对于性能的提升有诸多贡献,但是也存在一个常见的问题即缓存的数据与实际数据库的数据不同步,存在一定时间的延迟。为了解决这个问题,SpaceBuilder采用了缓存的手动过期策略。例如,以下代码用于获取ForumThread,并把数据放入缓存:

public static ForumThread GetThread(int threadID, bool useCache)
        {
            string cacheKey = string.Format("ForumThread:{0}", threadID);
            ForumThread thread = null;
            if (useCache)
            {
thread = CacheManager.Get(cacheKey) as ForumThread;
            }
            if (thread == null)
            {
                thread = ForumDataProvider.Instance().GetThread(threadID);
                if (useCache)
                {
CacheManager.Add(cacheKey, thread, SPBCacheManager.CachingExpirationType.SingleObject);
                }
            }
            return thread;
        }

对于该缓存,只有两种情况需要使其失效:该BlogThread被修改及被删除,因此我们应该在以下代码中手动使其失效:

public static void UpdateThread(ForumThread thread)
        {
            #region 设置AuditingStatus
            if (Auditings.NeedAuditing(thread.UserID, AuditingItemKeys.Instance().ForumThread(),
 AuditingStrictDegrees.Update))
                thread.IsApproved = false;
            #endregion
            thread.Subject = WebUtils.HtmlEncode(thread.Subject);
            ForumEvents.PreBeforeForumThreadChange(thread, ObjectState.Update);
            ForumEvents.BeforeForumThreadChange(thread, ObjectState.Update);
            ForumDataProvider.Instance().CreateUpadateThread(thread, DataProviderAction.Update);
            ForumEvents.AfterForumThreadChange(thread, ObjectState.Update);
            //清除缓存
            ClearCache(thread.SectionID, thread.ThreadID);
        }

        public static void DeleteThread(int threadID)
        {
            ForumThread thread = ForumThreads.GetThread(threadID);
            if (thread != null)
            {
                #region 删除附件
                ForumPostQuery query = new ForumPostQuery();
                query.EnablePaging = false;
                query.PageSize = ValueHelper.GetSafeSqlInt(int.MaxValue);
                query.IsApproved = null;
                query.ThreadID = thread.ThreadID;

                //删除回复附件
                PagingDataSet<ForumPost> ps = ForumPosts.GetPosts(query);
                foreach (ForumPost fp in ps.Records)
                {
                    ForumAttachmentManager.Instance().DeleteAttachmentsByAssociateID(fp.PostID);
                }

                //删除主题附件
                ForumAttachmentManager.Instance().DeleteAttachmentsByAssociateID(thread.PostID);                
                #endregion

                ForumEvents.PreBeforeForumThreadChange(thread, ObjectState.Delete);
                ForumEvents.BeforeForumThreadChange(thread, ObjectState.Delete);

                ForumDataProvider.Instance().DeletePost(thread.PostID);

                ForumEvents.AfterForumThreadChange(thread, ObjectState.Delete);
                //清除缓存
                ClearCache(thread.SectionID, thread.ThreadID); 
            }
        }

/// <summary>
        /// 清除相关缓存
        ///</summary>        
        private static void ClearCache(int sectionID, int threadID)
        {
            if (threadID > 0)
            {
                CacheManager.Remove(string.Format("ForumThread:{0}", threadID));
                CacheManager.RemoveItemsByStartsWith(string.Format("ForumPostSet::ThreadID:{0}", threadID));
            }

            if (sectionID > 0)
            {
                CacheManager.RemoveItemsByStartsWith(string.Format("ForumThreads::SectionID:{0}", sectionID));
                CacheManager.RemoveItemsByStartsWith(string.Format("ForumThreads::SectionID:{0}", -1));
            }
            else
            {
                CacheManager.RemoveItemsByStartsWith("ForumThreads::");
            }
        }

所以为了实施缓存的手动过期策略,一定要全面分析会影响某一缓存的所有操作,然后在这些操作中清除相应的缓存。

注意事项

  1. 每个应用建立一个自己的缓存区间(CacheManager),在web.config中进行配置;
  2. CacheKey大小写不敏感;
  3. CacheKey一定要保持唯一,需要制定CacheKey的命名规则;


参考资料[ ]