中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

Lind.DDD.Caching分(fen)布式數據集(ji)緩存介紹

回到目錄

戲說當年

大叔原創的分布式數據集緩存在之前的企業級框架里介紹過,大家可以關注《我心中的核心組件(可插拔的AOP)~第二回 緩存攔截器》,而今(jin)天(tian)主要對Lind.DDD.Caching進(jin)行(xing)(xing)更全面的(de)(de)(de)(de)(de)解(jie)決,設計思想(xiang)和(he)主要核(he)心(xin)內容進(jin)行(xing)(xing)講解(jie)。其實(shi)在(zai)很(hen)多緩(huan)存(cun)(cun)架構在(zai)業(ye)界有(you)很(hen)多,向(xiang).net運行(xing)(xing)時(shi)里也(ye)(ye)有(you)Cache,也(ye)(ye)可以實(shi)現(xian)簡單的(de)(de)(de)(de)(de)數據(ju)(ju)緩(huan)存(cun)(cun)的(de)(de)(de)(de)(de)功能,向(xiang)前幾年頁面的(de)(de)(de)(de)(de)靜態化比(bi)較流行(xing)(xing),就出(chu)現(xian)了(le)很(hen)多Http的(de)(de)(de)(de)(de)“攔截(jie)器“,對當前HTTP響應的(de)(de)(de)(de)(de)內容進(jin)行(xing)(xing)完整的(de)(de)(de)(de)(de)頁面緩(huan)存(cun)(cun),緩(huan)存(cun)(cun)的(de)(de)(de)(de)(de)文件大(da)多數存(cun)(cun)儲到(dao)磁(ci)盤里,訪問的(de)(de)(de)(de)(de)時(shi)間直接將磁(ci)盤上的(de)(de)(de)(de)(de)HTML文件進(jin)行(xing)(xing)輸出(chu),不(bu)用(yong)asp.net進(jin)行(xing)(xing)解(jie)析(xi),也(ye)(ye)省去了(le)鏈(lian)數據(ju)(ju)庫的(de)(de)(de)(de)(de)操(cao)作,所以在(zai)性能上有(you)所提升,弊端(duan)就是和(he)當前的(de)(de)(de)(de)(de)頁面(HTML內容)耦(ou)合(he)度太(tai)大(da),所以,現(xian)在(zai)用(yong)這種原始的(de)(de)(de)(de)(de)緩(huan)存(cun)(cun)方式(shi)的(de)(de)(de)(de)(de)項目越(yue)來(lai)越(yue)少。

大叔的數據集緩存

比較頁面緩存(cun),數據(ju)集緩存(cun)就(jiu)感(gan)覺優(you)異了(le)(le)不(bu)少,它(ta)緩存(cun)的(de)(de)是(shi)數據(ju),而(er)不(bu)是(shi)頁面,即它(ta)省去了(le)(le)鏈接數據(ju)庫(ku)的(de)(de)時間,而(er)直接用緩存(cun),文件,redis等中(zhong)間件上(shang)返回內容(rong),當前你的(de)(de)中(zhong)間件為(wei)了(le)(le)提(ti)升(sheng)性(xing)能,可以采(cai)用集群機制(zhi),這在一些NoSql上(shang)實現非(fei)常容(rong)易(yi),或(huo)者(zhe)說(shuo)Nosql就(jiu)是(shi)為(wei)了(le)(le)緩存(cun)而(er)產生的(de)(de),呵呵!

緩存特性

這個CachingAttribute 特(te)性(xing)被使用者添加(jia)到指定(ding)的方法(fa)上,有get,put,remove等枚(mei)舉(ju)類型,分(fen)別為讀緩存,寫緩存和(he)刪除緩存。

  /// <summary>
    /// 表示由此特性所描(miao)述的方法,能(neng)夠獲得(de)來自(zi)Microsoft.Practices.EnterpriseLibrary.Caching基礎結構層所提供(gong)的緩存功(gong)能(neng)。
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=false)]
    public class CachingAttribute : Attribute
    {
        #region Ctor
        /// <summary>
        /// 初始化一個(ge)新的<c>CachingAttribute</c>類(lei)型。
        /// </summary>
        /// <param name="method">緩(huan)存(cun)方式。</param>
        public CachingAttribute(CachingMethod method)
        {
            this.Method = method;
        }
        /// <summary>
        /// 初始(shi)化一(yi)個新(xin)的<c>CachingAttribute</c>類型(xing)。
        /// </summary>
        /// <param name="method">緩存方(fang)式。</param>
        /// <param name="correspondingMethodNames">與(yu)當前(qian)緩(huan)存方(fang)式(shi)相關的方(fang)法名稱(cheng)。注:此參數僅(jin)在(zai)緩(huan)存方(fang)式(shi)為Remove時起作(zuo)用(yong)。</param>
        public CachingAttribute(CachingMethod method, params string[] correspondingMethodNames)
            : this(method)
        {
            this.CorrespondingMethodNames = correspondingMethodNames;
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// 獲取或設置緩存方式。
        /// </summary>
        public CachingMethod Method { get; set; }
        /// <summary>
        /// 獲取或設置一個(ge)<see cref="Boolean"/>值,該值表示當(dang)緩存方式為Put時,是否(fou)強制將值寫(xie)入緩存中。
        /// </summary>
        public bool Force { get; set; }
        /// <summary>
        /// 獲取(qu)或設置與當前(qian)緩(huan)存方(fang)式(shi)相關的方(fang)法(fa)名稱。注:此(ci)參數(shu)僅在緩(huan)存方(fang)式(shi)為Remove時起作用(yong)。
        /// </summary>
        public string[] CorrespondingMethodNames { get; set; }
        #endregion
    }

緩存攔截器

攔(lan)截器起源于面向切面的(de)(de)(de)編程aop里(li),它也是aop設計的(de)(de)(de)精髓,即將指(zhi)定(ding)方法攔(lan)截,然后注(zhu)入新的(de)(de)(de)代(dai)碼(ma)邏輯,在(zai)(zai)不(bu)修改原有代(dai)碼(ma)的(de)(de)(de)情況下,完成(cheng)這個功能,在(zai)(zai)攔(lan)截器里(li),我(wo)們為不(bu)同(tong)的(de)(de)(de)項目(mu)添加了(le)不(bu)同(tong)的(de)(de)(de)名(ming)稱,這是為了(le)避免在(zai)(zai)多項目(mu)情況下,緩(huan)(huan)存鍵名(ming)重復的(de)(de)(de)問題(ti),因為我(wo)們的(de)(de)(de)緩(huan)(huan)存內(nei)容(rong)都是存儲在(zai)(zai)同(tong)一個中(zhong)間件(jian)上(shang)的(de)(de)(de)。

    /// <summary>
    /// 表示用于方法緩存(cun)功(gong)能的攔截行為。
    /// </summary>
    public class CachingBehavior : IInterceptionBehavior
    {
        /// <summary>
        /// 緩存項(xiang)目(mu)名稱,每(mei)個項(xiang)目(mu)有自己(ji)的名稱
        /// 避免緩存鍵名(ming)重復
        /// </summary>
        static readonly string cacheProjectName = System.Configuration.ConfigurationManager.AppSettings["CacheProjectName"] ?? "DataSetCache";


        #region Private Methods
        /// <summary>
        /// 根(gen)據指定的(de)<see cref="CachingAttribute"/>以及<see cref="IMethodInvocation"/>實例,
        /// 獲取與某一(yi)特定參(can)數(shu)值相關(guan)的鍵名。
        /// </summary>
        /// <;param name="cachingAttribute"><see cref="CachingAttribute"/>實例。</param>
        /// <;param name="input"><see cref="IMethodInvocation"/>實例。</param>
        /// <returns>與某(mou)一(yi)特(te)定參數值相關(guan)的鍵名。</returns>
        private string GetValueKey(CachingAttribute cachingAttribute, IMethodInvocation input)
        {
            switch (cachingAttribute.Method)
            {
                // 如果是Remove,則不(bu)存在特定(ding)值鍵名,所有的以該(gai)方法名稱相關的緩存都需要清除
                case CachingMethod.Remove:
                    return null;
                case CachingMethod.Get:// 如果是(shi)Get或者Put,則需要(yao)產(chan)生一(yi)個針對特定參數(shu)值(zhi)的鍵名(ming)
                case CachingMethod.Put:
                    if (input.Arguments != null &&
                        input.Arguments.Count > 0)
                    {
                        var sb = new StringBuilder();
                        for (int i = 0; i < input.Arguments.Count; i++)
                        {
                            if (input.Arguments[i] == null)
                                break;

                            if (input.Arguments[i].GetType().BaseType == typeof(LambdaExpression))//lambda處理
                            {
                                string result = "";

                                try
                                {
                                    var exp = input.Arguments[i] as LambdaExpression;
                                    var arr = ((System.Runtime.CompilerServices.Closure)(((System.Delegate)(Expression.Lambda(exp).Compile().DynamicInvoke())).Target)).Constants;
                                    Type t = arr[0].GetType();
                                    foreach (var member in t.GetFields())
                                    {
                                        result += "_" + member.Name + "_" + t.GetField(member.Name).GetValue(arr[0]);
                                    }
                                    result = result.Remove(0, 1);
                                }
                                catch (NullReferenceException)
                                {
                                    //lambda表達式異(yi)常(chang),可(ke)能是(shi)沒有字段(duan),如這種格式i=&gt;true,會(hui)產生NullReferenceException異(yi)常(chang).
                                }

                                sb.Append(result.ToString());
                            }
                            else if (input.Arguments[i].GetType() != typeof(string)//類和結(jie)構體處理
                                && input.Arguments[i].GetType().BaseType.IsClass)
                            {
                                var obj = input.Arguments[i];
                                Type t = obj.GetType();
                                string result = "";
                                #region 提取類中的字段和屬性
                                foreach (var member in t.GetProperties())//公開屬性(xing)
                                {
                                    result += member.Name + "_" + t.GetProperty(member.Name).GetValue(obj) + "_";
                                }
                                foreach (var member in t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))//私有和公用字段
                                {
                                    result += member.Name + "_" + t.GetField(member.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(obj) + "_";
                                }
                                #endregion
                                result = result.Remove(result.Length - 1);
                                sb.Append(result.ToString());
                            }
                            else//簡單(dan)值類型(xing)處理
                            {
                                sb.Append(input.Arguments[i].ToString());
                            }

                            if (i != input.Arguments.Count - 1)
                                sb.Append("_");
                        }
                        return sb.ToString();
                    }
                    else
                        return "NULL";
                default:
                    throw new InvalidOperationException("無(wu)效(xiao)的緩存方(fang)式。");
            }
        }
        #endregion

        #region IInterceptionBehavior Members
        /// <summary>
        /// 獲取當(dang)前行為需要攔截(jie)的對象類型接口。
        /// </summary>
        /// <returns>所有需要攔(lan)截(jie)的對象(xiang)類型接口。</returns>
        public IEnumerable<Type> GetRequiredInterfaces()
        {
            return Type.EmptyTypes;
        }

        /// <summary>
        /// 通過實現(xian)此(ci)方法來攔(lan)截(jie)調用并執(zhi)行所(suo)需的(de)攔(lan)截(jie)行為(wei)。
        /// </summary>
        /// <param name="input">調用攔截(jie)目(mu)標時的輸入信息。</param>
        /// <param name="getNext">通(tong)過行為鏈來獲取下一(yi)個攔(lan)截行為的委(wei)托。</param>
        /// <returns>從攔(lan)截目標獲得的返回信息。</returns>
        public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
        {

            var method = input.MethodBase;
            //鍵值前綴
            string prefix = cacheProjectName + "_";
            var baseInterfaces = input.Target.GetType().GetInterfaces();
            if (baseInterfaces != null && baseInterfaces.Any())
            {
                foreach (var item in baseInterfaces)
                {
                    prefix += item.ToString() + "_";
                }
            }


            //鍵名(ming),在put和get時使用
            var key = prefix + method.Name;

            if (method.IsDefined(typeof(CachingAttribute), false))
            {
                var cachingAttribute = (CachingAttribute)method.GetCustomAttributes(typeof(CachingAttribute), false)[0];
                var valKey = GetValueKey(cachingAttribute, input);
                switch (cachingAttribute.Method)
                {
                    case CachingMethod.Get:
                        try
                        {
                            if (CacheManager.Instance.Exists(key, valKey))
                            {
                                var obj = CacheManager.Instance.Get(key, valKey);
                                var arguments = new object[input.Arguments.Count];
                                input.Arguments.CopyTo(arguments, 0);
                                return new VirtualMethodReturn(input, obj, arguments);
                            }
                            else
                            {
                                var methodReturn = getNext().Invoke(input, getNext);
                                CacheManager.Instance.Add(key, valKey, methodReturn.ReturnValue);
                                return methodReturn;
                            }
                        }
                        catch (Exception ex)
                        {
                            return new VirtualMethodReturn(input, ex);
                        }
                    case CachingMethod.Put:
                        try
                        {
                            var methodReturn = getNext().Invoke(input, getNext);
                            if (CacheManager.Instance.Exists(key))
                            {
                                if (cachingAttribute.Force)
                                {
                                    CacheManager.Instance.Remove(key);
                                    CacheManager.Instance.Add(key, valKey, methodReturn.ReturnValue);
                                }
                                else
                                    CacheManager.Instance.Put(key, valKey, methodReturn.ReturnValue);
                            }
                            else
                                CacheManager.Instance.Add(key, valKey, methodReturn.ReturnValue);
                            return methodReturn;
                        }
                        catch (Exception ex)
                        {
                            return new VirtualMethodReturn(input, ex);
                        }
                    case CachingMethod.Remove:
                        try
                        {
                            var removeKeys = cachingAttribute.CorrespondingMethodNames;
                            foreach (var removeKey in removeKeys)
                            {
                                string delKey = prefix + removeKey;
                                if (CacheManager.Instance.Exists(delKey))
                                    CacheManager.Instance.Remove(delKey);
                            }
                            var methodReturn = getNext().Invoke(input, getNext);
                            return methodReturn;
                        }
                        catch (Exception ex)
                        {
                            return new VirtualMethodReturn(input, ex);
                        }
                    default: break;
                }
            }

            return getNext().Invoke(input, getNext);
        }

        /// <summary>
        /// 獲取一個(ge)<see cref="Boolean"/>值,該值表示(shi)當前攔(lan)截(jie)行(xing)(xing)為被(bei)調用時,是否(fou)真的(de)需(xu)要執(zhi)行(xing)(xing)
        /// 某些(xie)操作(zuo)。
        /// </summary>
        public bool WillExecute
        {
            get { return true; }
        }

        #endregion
    }

緩存實現者

目前大(da)叔(shu)的(de)框架(jia)中,數據集(ji)緩存(cun)有redis和(he)內容(rong)兩種(zhong)實現(xian)方式,在多web服(fu)務器的(de)情況下,只能采用(yong)redis這種(zhong)中間存(cun)儲服(fu)務器。

緩存生產者

緩存生產(chan)者與日志,消息(xi)等生產(chan)者類似,由于全局使用一個實例即可,所(suo)以在設計(ji)時采用了單例模(mo)式,工廠模(mo)式,策略模(mo)式等,目(mu)前(qian)在工廠里只(zhi)有(you)EntLib內(nei)存緩存和redis分布式緩存兩種,詳(xiang)細請見代(dai)碼(ma)。

    /// <summary>
    /// 緩存持久化工廠類
    /// 可以由多種持久化的策(ce)略
    /// 策略模(mo)(mo)式和工(gong)廠模(mo)(mo)式的體現
    /// </summary>
    public sealed class CacheManager : ICacheProvider
    {
        #region Private Fields
        private readonly ICacheProvider _cacheProvider;
        private static readonly CacheManager _instance;
        #endregion

        #region Ctor
        static CacheManager() { _instance = new CacheManager(); }

        /// <summary>
        /// 對(dui)外不(bu)能創建類的實例
        /// </summary>
        private CacheManager()
        {
            string strategyName = ConfigConstants.ConfigManager.Config.AoP_CacheStrategy ?? "EntLib";

            switch (strategyName)
            {
                case "EntLib":
                    _cacheProvider = new EntLibCacheProvider();
                    break;
                case "Redis":
                    _cacheProvider = new RedisCacheProvider();
                    break;
                default:
                    throw new ArgumentException("緩存持久化方法不正確,目前(qian)只支持EntLib和Redis");
            }
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// 獲取(qu)<c>CacheManager</c>類型(xing)的單件(Singleton)實例。
        /// </summary>
        public static CacheManager Instance
        {
            get { return _instance; }
        }
        #endregion

        #region ICacheProvider Members
        /// <summary>
        /// 向(xiang)緩存(cun)中添(tian)加一個對象(xiang)。
        /// </summary>
        /// <param name="key">緩存(cun)的(de)鍵值(zhi),該值(zhi)通常是使用緩存(cun)機制(zhi)的(de)方法的(de)名稱。</param>
        /// <param name="valKey">緩存(cun)值的鍵(jian)值,該值通(tong)常是由(you)使用緩存(cun)機制的方法的參數值所產生。</param>
        /// <param name="value">需要緩存的(de)對象。</param>
        public void Add(string key, string valKey, object value)
        {
            _cacheProvider.Add(key, valKey, value);
        }
        /// <summary>
        /// 向(xiang)緩存中更(geng)新(xin)一個對(dui)象。
        /// </summary>
        /// <param name="key">緩存的(de)(de)鍵值,該(gai)值通常是(shi)使用緩存機制的(de)(de)方(fang)法(fa)的(de)(de)名(ming)稱(cheng)。</param>
        /// <param name="valKey">緩存值的鍵值,該值通常是由(you)使用緩存機制(zhi)的方法(fa)的參數值所(suo)產生。</param>
        /// <param name="value">需要緩(huan)存的對象。</param>
        public void Put(string key, string valKey, object value)
        {
            _cacheProvider.Put(key, valKey, value);
        }
        /// <summary>
        /// 從緩(huan)存中讀取對象。
        /// </summary>
        /// <param name="key">緩(huan)存(cun)的(de)(de)鍵(jian)值,該值通常(chang)是使用緩(huan)存(cun)機制的(de)(de)方法的(de)(de)名稱。</param>
        /// <param name="valKey">緩存值(zhi)(zhi)的鍵值(zhi)(zhi),該值(zhi)(zhi)通常是由使用緩存機(ji)制的方(fang)法的參數(shu)值(zhi)(zhi)所產生。</param>
        /// <returns>被緩存的對象(xiang)。</returns>
        public object Get(string key, string valKey)
        {
            return _cacheProvider.Get(key, valKey);
        }
        /// <summary>
        /// 從緩(huan)存中移(yi)除對象(xiang)。
        /// </summary>
        /// <param name="key">緩存的鍵(jian)值(zhi),該值(zhi)通常是使用(yong)緩存機制的方法的名稱。</param>
        public void Remove(string key)
        {
            _cacheProvider.Remove(key);
        }
        /// <summary>
        /// 獲取一(yi)個<see cref="Boolean"/>值,該值表示擁有(you)指(zhi)定鍵值的緩(huan)存是(shi)否(fou)存在(zai)。
        /// </summary>
        /// <param name="key">指定的鍵值。</param>
        /// <returns>如果緩存(cun)存(cun)在,則(ze)返回(hui)true,否則(ze)返回(hui)false。</returns>
        public bool Exists(string key)
        {
            return _cacheProvider.Exists(key);
        }
        /// <summary>
        /// 獲取一個<see cref="Boolean"/>值,該值表示擁有指定鍵值和緩(huan)存值鍵的緩(huan)存是否存在。
        /// </summary>
        /// <param name="key">指(zhi)定的(de)鍵值。</param>
        /// <param name="valKey">緩存值(zhi)鍵。</param>
        /// <returns>如(ru)果(guo)緩存存在,則返回true,否則返回false。</returns>
        public bool Exists(string key, string valKey)
        {
            return _cacheProvider.Exists(key, valKey);
        }
        #endregion
    }

最后,我(wo)(wo)們(men)的(de)(de)緩存使(shi)用(yong)需要在接(jie)口(kou)的(de)(de)方法(fa)(fa)(fa)或(huo)者虛方法(fa)(fa)(fa)上進行聲明(ming),因為(wei)我(wo)(wo)們(men)的(de)(de)攔(lan)截使(shi)用(yong)了Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension攔(lan)截器組件,實現原因是(shi)生成一個(ge)代理類,并重寫指定的(de)(de)被攔(lan)截的(de)(de)方法(fa)(fa)(fa),所以要求你(ni)的(de)(de)方法(fa)(fa)(fa)是(shi)接(jie)口(kou)方法(fa)(fa)(fa)或(huo)者虛方法(fa)(fa)(fa)。

感謝各位的耐心閱讀,請繼續關注Lind.DDD大叔框架設計437541737

回到目錄

 

posted @ 2016-01-29 16:38  張占嶺  閱讀(2085)  評論(1)    收藏  舉報