国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

一步步實(shí)現(xiàn)一個(gè)基本的緩存模塊·續(xù), 添加Memcached調(diào)用實(shí)現(xiàn)

2019-11-17 02:37:09
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

一步步實(shí)現(xiàn)一個(gè)基本的緩存模塊·續(xù), 添加Memcached調(diào)用實(shí)現(xiàn)

jusfr 原創(chuàng),轉(zhuǎn)載請(qǐng)注明來(lái)自博客園。

在之前的實(shí)現(xiàn)中,我們初步實(shí)現(xiàn)了一個(gè)緩存模塊:包含一個(gè)基于Http請(qǐng)求的緩存實(shí)現(xiàn),一個(gè)基于HttPRuntime.Cache進(jìn)程級(jí)的緩存實(shí)現(xiàn),但觀察代碼,會(huì)發(fā)現(xiàn)如下問(wèn)題:

1. 有部分邏輯如 Boolean TryGet<T>(String key, out T entry) 的實(shí)現(xiàn)有重復(fù)現(xiàn)象,Do not repeat yourself 提醒我們這里可以改進(jìn);2. 分區(qū)特性雖然實(shí)現(xiàn)了,但是使用了額外的接口承載,而大多數(shù)運(yùn)用中,調(diào)用者無(wú)論是操作緩存項(xiàng)的創(chuàng)建還是過(guò)期,都不太關(guān)心分區(qū)參數(shù) Region;的機(jī)制問(wèn)題,計(jì)數(shù)和全部過(guò)期貌似不太現(xiàn)實(shí),從這個(gè)接口派生恐怕不妥,怎么辦?3. IHttpRuntimeCacheProvider 接口中功能太多,本文要添加一個(gè)基于 Memcached 的緩存實(shí)現(xiàn)類,而 Memcached 天然不支持遍歷等操作怎么辦?

處理第1個(gè)問(wèn)題,先梳理一下緩存獲取即 GetOrCreate 邏輯,多數(shù)情況是這樣的

1)嘗試從某容器或客戶端如 HttpContext.Current.Items、HttpRuntime.Cache、MemcachedClient 判斷緩存是否存在及獲取緩存對(duì)象;2)緩存對(duì)象存在時(shí)進(jìn)行類型對(duì)比,比如 id 已經(jīng)被緩存成整型,現(xiàn)在新接口嘗試將 Guid 類型寫(xiě)入,本文使用嚴(yán)格策略,該操作將拋出 InvalidOperationException 異常;3)緩存不存在時(shí),執(zhí)行委托計(jì)算出緩存值,將其寫(xiě)入容器;

可以看出, GetOrCreate 將調(diào)用 TryGet 方法及 Overwrite 方法,我們可以使用抽象類,將前者寫(xiě)成具體實(shí)現(xiàn),將后兩者寫(xiě)成抽象方法,由具體子類去實(shí)現(xiàn)。

 1     public interface ICacheProvider { 2         Boolean TryGet<T>(String key, out T entry); 3         T GetOrCreate<T>(String key, Func<T> function); 4         T GetOrCreate<T>(String key, Func<String, T> factory); 5         void Overwrite<T>(String key, T entry); 6         void Expire(String key); 7     } 8  9     public abstract class CacheProvider : ICacheProvider {10         protected virtual String BuildCacheKey(String key) {11             return key;12         }13         14         protected abstract Boolean InnerTryGet(String key, out Object entry);15 16         public virtual Boolean TryGet<T>(String key, out T entry) {17             String cacheKey = BuildCacheKey(key);18             Object cacheEntry;19             Boolean exist = InnerTryGet(cacheKey, out cacheEntry);20             if (exist) {21                 if (cacheEntry != null) {22                     if (!(cacheEntry is T)) {23                         throw new InvalidOperationException(String.Format("緩存項(xiàng)`[{0}]`類型錯(cuò)誤, {1} or {2} ?",24                             key, cacheEntry.GetType().FullName, typeof(T).FullName));25                     }26                     entry = (T)cacheEntry;                    27                 }28                 else {29                     entry = (T)((Object)null);30                 }31             }32             else {33                 entry = default(T);34             }35             return exist;36         }37 38         public virtual T GetOrCreate<T>(String key, Func<T> function) {39             T entry;40             if (TryGet(key, out entry)) {41                 return entry;42             }43             entry = function();44             Overwrite(key, entry);45             return entry;46         }47 48         public virtual T GetOrCreate<T>(String key, Func<String, T> factory) {49             T entry;50             if (TryGet(key, out entry)) {51                 return entry;52             }53             entry = factory(key);54             Overwrite(key, entry);55             return entry;56         }57 58         public abstract void Overwrite<T>(String key, T value);59 60         public abstract void Expire(String key);61     }

抽象類 CacheProvider 的 InnerTryGet、Overwrite、Expire 是需要實(shí)現(xiàn)類來(lái)完成的,GetOrCreate 調(diào)用它們來(lái)完成核心邏輯;于是HttpContextCacheProvider 的實(shí)現(xiàn),邏輯在父類實(shí)現(xiàn)后,看起來(lái)非常簡(jiǎn)潔了:

 1     public class HttpContextCacheProvider : CacheProvider, ICacheProvider { 2         private const String _prefix = "HttpContextCacheProvider_"; 3         protected override String BuildCacheKey(String key) { 4             return String.Concat(_prefix, key); 5         } 6  7         protected override Boolean InnerTryGet(String key, out Object entry) { 8             Boolean exist = false; 9             entry = null;10             if (HttpContext.Current.Items.Contains(key)) {11                 exist = true;12                 entry = HttpContext.Current.Items[key];13             }14             return exist;15         }16 17         public override void Overwrite<T>(String key, T entry) {18             HttpContext.Current.Items[BuildCacheKey(key)] = entry;19         }20 21         public override void Expire(String key) {22             HttpContext.Current.Items.Remove(BuildCacheKey(key));23         }24     }

這里不準(zhǔn)備為基于 HttpContext 的緩存提供太多特性,但基于 HttpRuntime.Cache 的緩存就需要像過(guò)期之類的功能,在實(shí)現(xiàn)之前先考慮問(wèn)題2

首先,既然用戶沒(méi)有必要甚至不知道分區(qū)存在,我們直接實(shí)現(xiàn)支持分區(qū)特性的子類好了;然后,計(jì)數(shù)與過(guò)期功能 HttpRuntime.Cache 支持但 Memcached 不,所以這部分功能需要從 IHttpRuntimeCacheProvider 中拆分出來(lái),沒(méi)錯(cuò),擴(kuò)展方法!于是拆分如下:

 1     public interface IRegion { 2         String Region { get; } 3     } 4  5     public interface IHttpRuntimeCacheProvider : ICacheProvider { 6         T GetOrCreate<T>(String key, Func<T> function, TimeSpan slidingExpiration); 7         T GetOrCreate<T>(String key, Func<T> function, DateTime absoluteExpiration); 8         void Overwrite<T>(String key, T value, TimeSpan slidingExpiration); 9         void Overwrite<T>(String key, T value, DateTime absoluteExpiration);        10     }

其中IHttpRuntimeCacheProvider接口定義了帶有過(guò)期參數(shù)的緩存操作方法,我們需要實(shí)現(xiàn)抽象方法與額外接口如下:

 1 public class HttpRuntimeCacheProvider : CacheProvider, IHttpRuntimeCacheProvider, IRegion { 2         private static readonly Object _nullEntry = new Object(); 3         private String _prefix = "HttpRuntimeCacheProvider_"; 4  5         public virtual String Region { get; private set; } 6  7         public HttpRuntimeCacheProvider() { 8         } 9 10         public HttpRuntimeCacheProvider(String region) {11             Region = region;12         }13 14         protected override bool InnerTryGet(String key, out object entry) {15             entry = HttpRuntime.Cache.Get(key);16             return entry != null;17         }18 19         protected override String BuildCacheKey(String key) {20             //Region 為空將被當(dāng)作  String.Empty 處理21             return Region == null22                 ? String.Concat(_prefix, key)23                 : String.Concat(_prefix, Region, key);24         }25 26         private Object BuildCacheEntry<T>(T value) {27             Object entry = value;28             if (value == null) {29                 entry = _nullEntry;30             }31             return entry;32         }33 34 35         public T GetOrCreate<T>(String key, Func<T> function, TimeSpan slidingExpiration) {36             T value;37             if (TryGet<T>(key, out value)) {38                 return value;39             }40             value = function();41             Overwrite(key, value, slidingExpiration);42             return value;43         }44 45         public T GetOrCreate<T>(String key, Func<T> function, DateTime absoluteExpiration) {46             T value;47             if (TryGet<T>(key, out value)) {48                 return value;49             }50             value = function();51             Overwrite(key, value, absoluteExpiration);52             return value;53         }54 55         public override void Overwrite<T>(String key, T value) {56             HttpRuntime.Cache.Insert(BuildCacheKey(key), BuildCacheEntry<T>(value));57         }58 59         //slidingExpiration 時(shí)間內(nèi)無(wú)訪問(wèn)則過(guò)期60         public void Overwrite<T>(String key, T value, TimeSpan slidingExpiration) {61             HttpRuntime.Cache.Insert(BuildCacheKey(key), BuildCacheEntry<T>(value), null,62                 Cache.NoAbsoluteExpiration, slidingExpiration);63         }64 65         //absoluteExpiration 時(shí)過(guò)期66         public void Overwrite<T>(String key, T value, DateTime absoluteExpiration) {67             HttpRuntime.Cache.Insert(BuildCacheKey(key), BuildCacheEntry<T>(value), null,68                 absoluteExpiration, Cache.NoSlidingExpiration);69         }70 71         public override void Expire(String key) {72             HttpRuntime.Cache.Remove(BuildCacheKey(key));73         }74 75         internal Boolean Hit(DictionaryEntry entry) {76             return (entry.Key is String)77                 && ((String)entry.Key).StartsWith(BuildCacheKey(String.Empty));78         }79     }

HttpRuntimeCacheProvider 暴露了一個(gè) internal 修飾的方法,提供給擴(kuò)展方法調(diào)用:

 1     public static
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 奇台县| 芦山县| 夏邑县| 南安市| 西藏| 香港 | 西盟| 鄄城县| 洛浦县| 安徽省| 焉耆| 惠州市| 渝中区| 涟源市| 广南县| 健康| 清河县| 偏关县| 钦州市| 潼南县| 山东| 瑞金市| 平定县| 晋州市| 洞口县| 自贡市| 德江县| 民丰县| 赞皇县| 汕头市| 喜德县| 凭祥市| 景泰县| 乌海市| 禹城市| 南阳市| 临汾市| 东台市| 栖霞市| 民勤县| 浑源县|