zoukankan      html  css  js  c++  java
  • .NET4.0的可扩展缓存系统

    .NET Framework中,叫做System.Runtime.Caching,这不仅是个缓存库,还是个框架,可以在上面开发自己的库。ObjectCache定义了所有缓存都要实现的通用操作。与之搭配的是个内存缓存实现,叫做MemoryCache。这个缓存系统的结构如下:

    image

    上图大家可以看出来对应那些产品了吗?

    下面我给大家介绍一个实现这样一个架构的代码示例,代码的核心就是ObjectCache:

    定义一个抽象的Provider接口:

       1: public interface ICacheBuilder
       2: {
       3:     ObjectCache GetInstance();
       4:     string DefaultRegionName { get; }
       5: }

    In-memory提供者的实现使用MemoryCache:

       1: public class MemoryCacheBuilder : ICacheBuilder
       2: {
       3:     public MemoryCacheBuilder() { }
       4:  
       5:     public ObjectCache GetInstance()
       6:     {
       7:         return MemoryCache.Default;
       8:     }
       9:  
      10:     public string DefaultRegionName
      11:     {
      12:         get { return null; }
      13:     }
      14: }

    分布式缓存提供者Memcached:

       1: public class MemcachedCache : ObjectCache, ICacheBuilder
       2: {
       3:     private long _lDefaultExpireTime = 3600; // default Expire Time
       4:     private MemcachedClient _client = null;
       5:     #region ICache Members
       6:  
       7:     public MemcachedCache()
       8:     {
       9:         this._client = MemcachedClientService.Instance.Client;
      10:     }
      11:  
      12:     public override void Set(string key, object value, System.DateTimeOffset absoluteExpiration, string regionName = null)
      13:     {
      14:         Enforce.NotNull(key, "key");
      15:         CacheItem item = new CacheItem(key, value, regionName);
      16:         CacheItemPolicy policy = new CacheItemPolicy();
      17:         policy.AbsoluteExpiration = absoluteExpiration;
      18:  
      19:         Set(item, policy);
      20:     }
      21:  
      22:     public override void Set(CacheItem item, CacheItemPolicy policy)
      23:     {
      24:         if (item == null || item.Value == null)
      25:             return;
      26:  
      27:         item.Key = item.Key.ToLower();
      28:  
      29:         if (policy != null && policy.ChangeMonitors != null && policy.ChangeMonitors.Count > 0)
      30:             throw new NotSupportedException("Change monitors are not supported");
      31:  
      32:         // max timeout in scaleout = 65535
      33:         TimeSpan expire = (policy.AbsoluteExpiration.Equals(null)) ?
      34:                             policy.SlidingExpiration :
      35:                             (policy.AbsoluteExpiration - DateTimeOffset.Now);
      36:  
      37:         double timeout = expire.TotalMinutes;
      38:         if (timeout > 65535)
      39:             timeout = 65535;
      40:         else if (timeout > 0 && timeout < 1)
      41:             timeout = 1;
      42:  
      43:         this._client.Store(Enyim.Caching.Memcached.StoreMode.Set, item.Key.ToString(), item.Value);
      44:  
      45:     }
      46:  
      47:     public override object this[string key]
      48:     {
      49:         get
      50:         {
      51:             return Get(key);
      52:         }
      53:         set
      54:         {
      55:             Set(key, value, null);
      56:         }
      57:     }
      58:  
      59:     public override object AddOrGetExisting(string key, object value, CacheItemPolicy policy, string regionName = null)
      60:     {
      61:         CacheItem item = GetCacheItem(key, regionName);
      62:         if (item == null)
      63:         {
      64:             Set(new CacheItem(key, value, regionName), policy);
      65:             return value;
      66:         }
      67:  
      68:         return item.Value;
      69:     }
      70:  
      71:     public override CacheItem AddOrGetExisting(CacheItem value, CacheItemPolicy policy)
      72:     {
      73:         CacheItem item = GetCacheItem(value.Key, value.RegionName);
      74:         if (item == null)
      75:         {
      76:             Set(value, policy);
      77:             return value;
      78:         }
      79:  
      80:         return item;
      81:     }
      82:  
      83:     public override object AddOrGetExisting(string key, object value, System.DateTimeOffset absoluteExpiration, string regionName = null)
      84:     {
      85:         CacheItem item = new CacheItem(key, value, regionName);
      86:         CacheItemPolicy policy = new CacheItemPolicy();
      87:         policy.AbsoluteExpiration = absoluteExpiration;
      88:  
      89:         return AddOrGetExisting(item, policy);
      90:     }
      91:  
      92:     public override bool Contains(string key, string regionName = null)
      93:     {
      94:         return false;
      95:     }
      96:  
      97:     public override CacheEntryChangeMonitor CreateCacheEntryChangeMonitor(System.Collections.Generic.IEnumerable<string> keys, string regionName = null)
      98:     {
      99:         throw new System.NotImplementedException();
     100:     }
     101:  
     102:     public override DefaultCacheCapabilities DefaultCacheCapabilities
     103:     {
     104:         get
     105:         {
     106:             return
     107:                 DefaultCacheCapabilities.OutOfProcessProvider |
     108:                 DefaultCacheCapabilities.AbsoluteExpirations |
     109:                 DefaultCacheCapabilities.SlidingExpirations |
     110:                 DefaultCacheCapabilities.CacheRegions;
     111:         }
     112:     }
     113:  
     114:     public override object Get(string key, string regionName = null)
     115:     {
     116:         key = key.ToLower();
     117:  
     118:         return this._client.Get(key);
     119:     }
     120:  
     121:     public override CacheItem GetCacheItem(string key, string regionName = null)
     122:     {
     123:         object value = Get(key, regionName);
     124:         if (value != null)
     125:             return new CacheItem(key, value, regionName);
     126:  
     127:         return null;
     128:     }
     129:  
     130:     public override long GetCount(string regionName = null)
     131:     {
     132:         return -1;
     133:     }
     134:  
     135:     protected override System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<string, object>> GetEnumerator()
     136:     {
     137:           throw new System.NotImplementedException();
     138:     }
     139:  
     140:     public override System.Collections.Generic.IDictionary<string, object> GetValues(System.Collections.Generic.IEnumerable<string> keys, string regionName = null)
     141:     {
     142:         throw new System.NotImplementedException();
     143:     }
     144:  
     145:     public override string Name
     146:     {
     147:         get { return "MemcachedProvider"; }
     148:     }
     149:  
     150:     public override object Remove(string key, string regionName = null)
     151:     {
     152:         key = key.ToLower();
     153:         return this._client.Remove(key);
     154:     }
     155:  
     156:     public override void Set(string key, object value, CacheItemPolicy policy, string regionName = null)
     157:     {
     158:         Set(new CacheItem(key, value, regionName), policy);
     159:     }
     160:  
     161:     #endregion
     162:  
     163:     #region ICacheBuilder Members
     164:  
     165:     public ObjectCache GetInstance()
     166:     {
     167:         return this;
     168:     }
     169:  
     170:     public string DefaultRegionName
     171:     {
     172:         get { throw new NotImplementedException(); }
     173:     }
     174:  
     175:     #endregion
     176: }

    分布式缓存提供者Windows Server AppFabric Caching:

       1: public class AppFabricCacheProvider : ObjectCache, ICacheBuilder
       2: {
       3:     public static DataCache factory = null;
       4:     public static object syncObj = new object();
       5:  
       6:     public override object AddOrGetExisting(string key, object value, CacheItemPolicy policy, string regionName = null)
       7:     {
       8:         CacheItem item = GetCacheItem(key, regionName);
       9:         if (item == null)
      10:         {
      11:             Set(new CacheItem(key, value, regionName), policy);
      12:             return value;
      13:         }
      14:  
      15:         return item.Value;
      16:     }
      17:  
      18:     public override CacheItem AddOrGetExisting(CacheItem value, CacheItemPolicy policy)
      19:     {
      20:         CacheItem item = GetCacheItem(value.Key, value.RegionName);
      21:         if (item == null)
      22:         {
      23:             Set(value, policy);
      24:             return value;
      25:         }
      26:  
      27:         return item;
      28:     }
      29:  
      30:     public override object AddOrGetExisting(string key, object value, System.DateTimeOffset absoluteExpiration, string regionName = null)
      31:     {
      32:         CacheItem item = new CacheItem(key, value, regionName);
      33:         CacheItemPolicy policy = new CacheItemPolicy();
      34:         policy.AbsoluteExpiration = absoluteExpiration;
      35:  
      36:         return AddOrGetExisting(item, policy);
      37:     }
      38:  
      39:     public override bool Contains(string key, string regionName = null)
      40:     {
      41:         return Get(key, regionName) != null;
      42:     }
      43:  
      44:     public override CacheEntryChangeMonitor CreateCacheEntryChangeMonitor(System.Collections.Generic.IEnumerable<string> keys, string regionName = null)
      45:     {
      46:         throw new NotImplementedException();
      47:     }
      48:  
      49:     public override DefaultCacheCapabilities DefaultCacheCapabilities
      50:     {
      51:         get
      52:         {
      53:             return
      54:                 DefaultCacheCapabilities.OutOfProcessProvider |
      55:                 DefaultCacheCapabilities.AbsoluteExpirations |
      56:                 DefaultCacheCapabilities.SlidingExpirations |
      57:                 DefaultCacheCapabilities.CacheRegions;
      58:         }
      59:     }
      60:  
      61:     public override object Get(string key, string regionName = null)
      62:     {
      63:         key = key.ToLower();
      64:         CreateRegionIfNeeded();
      65:  
      66:         return (regionName == null) ?
      67:             CacheFactory.Get(key) :
      68:             CacheFactory.Get(key, regionName);
      69:     }
      70:  
      71:     public override CacheItem GetCacheItem(string key, string regionName = null)
      72:     {
      73:         object value = Get(key, regionName);
      74:         if (value != null)
      75:             return new CacheItem(key, value, regionName);
      76:  
      77:         return null;
      78:     }
      79:  
      80:     public override long GetCount(string regionName = null)
      81:     {
      82:         if (string.IsNullOrEmpty(regionName))
      83:             throw new NotSupportedException();
      84:  
      85:         return CacheFactory.GetObjectsInRegion(regionName).LongCount();
      86:     }
      87:  
      88:     protected override System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<string, object>> GetEnumerator()
      89:     {
      90:         throw new NotSupportedException();
      91:     }
      92:  
      93:     public override System.Collections.Generic.IDictionary<string, object> GetValues(System.Collections.Generic.IEnumerable<string> keys, string regionName = null)
      94:     {
      95:         if (string.IsNullOrEmpty(regionName))
      96:             throw new NotSupportedException();
      97:  
      98:         return CacheFactory.GetObjectsInRegion(regionName).ToDictionary(x => x.Key, x => x.Value);
      99:     }
     100:  
     101:     public override string Name
     102:     {
     103:         get { return "AppFabric"; }
     104:     }
     105:  
     106:     public override object Remove(string key, string regionName = null)
     107:     {
     108:         key = key.ToLower();
     109:         CreateRegionIfNeeded();
     110:  
     111:         return (regionName == null) ?
     112:             CacheFactory.Remove(key) :
     113:             CacheFactory.Remove(key, regionName);
     114:     }
     115:  
     116:     public override void Set(string key, object value, CacheItemPolicy policy, string regionName = null)
     117:     {
     118:         Set(new CacheItem(key, value, regionName), policy);
     119:     }
     120:  
     121:     public override void Set(CacheItem item, CacheItemPolicy policy)
     122:     {
     123:         if (item == null || item.Value == null)
     124:             return;
     125:  
     126:         if (policy != null && policy.ChangeMonitors != null && policy.ChangeMonitors.Count > 0)
     127:             throw new NotSupportedException("Change monitors are not supported");
     128:  
     129:         item.Key = item.Key.ToLower();
     130:         CreateRegionIfNeeded();
     131:  
     132:         TimeSpan expire = (policy.AbsoluteExpiration.Equals(null)) ?
     133:             policy.SlidingExpiration :
     134:             (policy.AbsoluteExpiration - DateTimeOffset.Now);
     135:  
     136:         if (string.IsNullOrEmpty(item.RegionName))
     137:             CacheFactory.Put(item.Key, item.Value, expire);
     138:         else
     139:             CacheFactory.Put(item.Key, item.Value, expire, item.RegionName);
     140:     }
     141:  
     142:     private static DataCache CacheFactory
     143:     {
     144:         get
     145:         {
     146:             if (factory == null)
     147:             {
     148:                 lock (syncObj)
     149:                 {
     150:                     if (factory == null)
     151:                     {
     152:                         DataCacheFactory cacheFactory = new DataCacheFactory();
     153:                         factory = cacheFactory.GetDefaultCache();
     154:                     }
     155:                 }
     156:             }
     157:  
     158:             return factory;
     159:         }
     160:     }
     161:  
     162:     private void CreateRegionIfNeeded()
     163:     {
     164:         try
     165:         {
     166:             CacheFactory.CreateRegion(DefaultRegionName);
     167:         }
     168:         catch (DataCacheException ex)
     169:         {
     170:             if (!ex.ErrorCode.Equals(DataCacheErrorCode.RegionAlreadyExists))
     171:                 throw ex;
     172:         }
     173:     }
     174:  
     175:     public override void Set(string key, object value, System.DateTimeOffset absoluteExpiration, string regionName = null)
     176:     {
     177:         CacheItem item = new CacheItem(key, value, regionName);
     178:         CacheItemPolicy policy = new CacheItemPolicy();
     179:         policy.AbsoluteExpiration = absoluteExpiration;
     180:  
     181:         Set(item, policy);
     182:     }
     183:  
     184:     public override object this[string key]
     185:     {
     186:         get
     187:         {
     188:             return Get(key, DefaultRegionName);
     189:         }
     190:         set
     191:         {
     192:             Set(key, value, null, DefaultRegionName);
     193:         }
     194:     }
     195:  
     196:     public ObjectCache GetInstance()
     197:     {
     198:         return this;
     199:     }
     200:  
     201:     public string DefaultRegionName
     202:     {
     203:         get
     204:         {
     205:             string defaultRegion= FrameworkConfiguationManager.GetConfiguration().GetAppVariable("AppFabricCacheDefaultRegion");
     206:             if (string.IsNullOrEmpty(defaultRegion))
     207:             {
     208:                 defaultRegion = "Default";
     209:             }
     210:             return defaultRegion;
     211:         }
     212:     }
     213: }

    输出缓存对于改善性能有很大好处,在ASP.NET 4.0中可以自定义输出缓存的策略,比如把输出保存在磁盘中,外部的memcached服务中等等。甚至还可以定义一些高级规则,比如为A页面使用A输出缓存策略来把数据保存于内存中,为B页面使用B输出缓存策略来把数据保存于磁盘中。image

    代码例子可以参看文章http://www.buraksenyurt.com/post/AspNet-40-Custom-Cache-Provider.aspx,在web.config中配置

       1: <caching>
       2:         <outputCache defaultProvider="AspNetInternalProvider">
       3:           <providers>
       4:             <add name="DiskBasedCacheProvider" type="CustomCaching.DiskCacheProvider,CustomCaching"/>
       5:           </providers>
       6:         </outputCache>
       7:       </caching>

    在ASP.NET 4 的默认输出缓存策略中。所有的HTTP响应、所呈现的页面和控件缓存均使用上例所示的默认输出缓存提供程序(其中defaultProvider属性值为AspNetInternalProvider)。通过为defaultProvider指定不同的提供程序。就可以更改web应用程序的默认输出缓存提供程序。

    另外,还可以针对每个用户控件和各个请求选择不同的输出缓存提供程序。要为不同的Web用户控件选择不同的输出缓存提供程序,最简便的方法是设置页面或控件指令中新增加的providerName属性,如下面的示例所示:

    <%@ OutputCache Duration="60" VaryByParam="None"  providerName="DiskBasedCacheProvider" %>

    若要为某个HTTP请求指定不同的输出缓存提供程序,可以覆盖Global.asax文件中新增加的GetOutputCacheProviderName方法,以编程的方式指定要用于特定请求的提供程序。

    参看文章:.NET 4.0新增可扩展缓存

    欢迎大家扫描下面二维码成为我的客户,为你服务和上云

  • 相关阅读:
    例子:动能并不是特别强(2-3)后,下M5的同时,也是恢复期到期的前一天
    .NET 自带的动态代理+Expression 实现AOP
    自旋锁-SpinLock(.NET 4.0+)
    使用Nito.AsyncEx实现异步锁
    C# 两行代码实现 延迟加载的单例模式(线程安全)
    C++ 用于大型程序的工具
    C++ 模板与泛型编程
    C++ 面向对象编程
    C++ 重载操作符与转换
    C++ 复制控制
  • 原文地址:https://www.cnblogs.com/shanyou/p/1769547.html
Copyright © 2011-2022 走看看