緩存篇~第七回 Redis實現基於方法簽名的數據集緩存(可控更新,分布式數據緩存)


返回目錄

本篇文章可以說是第六回 Microsoft.Practices.EnterpriseLibrary.Caching實現基於方法簽名的數據集緩存(可控更新,WEB端數據緩存)的續篇,事實上,有EnterpriseLibrary.Caching也只是實現緩存持久化的一種方式,而Redis做為成熟的分布式存儲中間件來說,實現這個數據集緩存功能顯得更加得心應手,也更加滿足大型網站的設計規則。(在多web服務器時(web端實現負載均衡,反向代理),EnterpriseLibrary.Caching顯得沒什么作為,而這時,分布式緩存就可以一顯身手了,它可以很輕松的將緩存服務器部署到第三方服務器上,解決了上面的問題)

一個標准,多種實現,面向對象的真諦:多態性,如果你問我接口有什么用,那么本篇文章可以告訴你答案:根據不同的場合,使用不同的持久化方式去存儲數據。

下面是緩存標准接口ICacheProvider

 /// <summary>
    /// 表示實現該接口的類型是能夠為應用程序提供緩存機制的類型。
    /// 這可以有多種實現機制
    /// </summary>
    public interface ICacheProvider
    {
        #region Methods
        /// <summary>
        /// 向緩存中添加一個對象。
        /// </summary>
        /// <param name="key">緩存的鍵值,該值通常是使用緩存機制的方法的名稱。</param>
        /// <param name="valKey">緩存值的鍵值,該值通常是由使用緩存機制的方法的參數值所產生。</param>
        /// <param name="value">需要緩存的對象。</param>
        void Add(string key, string valKey, object value);
        /// <summary>
        /// 向緩存中更新一個對象。
        /// </summary>
        /// <param name="key">緩存的鍵值,該值通常是使用緩存機制的方法的名稱。</param>
        /// <param name="valKey">緩存值的鍵值,該值通常是由使用緩存機制的方法的參數值所產生。</param>
        /// <param name="value">需要緩存的對象。</param>
        void Put(string key, string valKey, object value);
        /// <summary>
        /// 從緩存中讀取對象。
        /// </summary>
        /// <param name="key">緩存的鍵值,該值通常是使用緩存機制的方法的名稱。</param>
        /// <param name="valKey">緩存值的鍵值,該值通常是由使用緩存機制的方法的參數值所產生。</param>
        /// <returns>被緩存的對象。</returns>
        object Get(string key, string valKey);
        /// <summary>
        /// 從緩存中移除對象。
        /// </summary>
        /// <param name="key">緩存的鍵值,該值通常是使用緩存機制的方法的名稱。</param>
        void Remove(string key);
        /// <summary>
        /// 獲取一個<see cref="Boolean"/>值,該值表示擁有指定鍵值的緩存是否存在。
        /// </summary>
        /// <param name="key">指定的鍵值。</param>
        /// <returns>如果緩存存在,則返回true,否則返回false。</returns>
        bool Exists(string key);
        /// <summary>
        /// 獲取一個<see cref="Boolean"/>值,該值表示擁有指定鍵值和緩存值鍵的緩存是否存在。
        /// </summary>
        /// <param name="key">指定的鍵值。</param>
        /// <param name="valKey">緩存值鍵。</param>
        /// <returns>如果緩存存在,則返回true,否則返回false。</returns>
        bool Exists(string key, string valKey);
        #endregion
    }

而這次我們使用Redis來作為實現持久化的方式,看一個RedisCacheProvider代碼,它為了兼容性,將Dictionary<string, object>類型改為了Dictionary<string, byte[]>類型,這種設計避免了很多錯誤,因為我們知道,數據在發送時,它會被序列化,而兼容性,

安全性,性能等最佳的方式就是二進制的方式,所以,我們使用它來對數據進行存儲。

    /// <summary>
    ///使用redis方式進行緩存持久化
    /// </summary>
    internal class RedisCacheProvider : ICacheProvider, IDisposable
    {
        private readonly IRedisClient _cacheManager = Redis.Client.RedisManager.GetClient();
        static byte[] Serialize(object data)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream rems = new MemoryStream();
            formatter.Serialize(rems, data);
            return rems.GetBuffer();
        }
        static object Deserialize(byte[] data)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream rems = new MemoryStream(data);
            data = null;
            return formatter.Deserialize(rems);
        }
        public void Add(string key, string valKey, object value)
        {
            byte[] byteValue = Serialize(value);
            using (var tbl = _cacheManager.GetTypedClient<Dictionary<string, byte[]>>())
            {
                Dictionary<string, byte[]> dict = null;
                if (tbl.ContainsKey(key))
                {
                    dict = (Dictionary<string, byte[]>)tbl.Lists[key][0];
                    dict[valKey] = byteValue;

                }
                else
                {
                    dict = new Dictionary<string, byte[]>();
                    dict.Add(valKey, byteValue);
                }
                Remove(key);
                tbl.Lists[key].Add(dict);
            }

        }

        public void Put(string key, string valKey, object value)
        {
            Add(key, valKey, value);
        }

        public object Get(string key, string valKey)
        {
            using (var tbl = _cacheManager.GetTypedClient<Dictionary<string, byte[]>>())
            {
                if (tbl.ContainsKey(key))
                {
                    Dictionary<string, byte[]> dict = (Dictionary<string, byte[]>)tbl.Lists[key][0];
                    if (dict != null && dict.ContainsKey(valKey))
                        return Deserialize(dict[valKey]);
                    else
                        return null;
                }
            }
            return null;

        }

        public void Remove(string key)
        {
            using (var tbl = _cacheManager.GetTypedClient<Dictionary<string, byte[]>>())
            {
                tbl.Lists[key].RemoveAll();
            }
        }

        public bool Exists(string key)
        {
            using (var tbl = _cacheManager.GetTypedClient<Dictionary<string, byte[]>>())
            {
                return tbl.ContainsKey(key);
            }
        }

        public bool Exists(string key, string valKey)
        {
            using (var tbl = _cacheManager.GetTypedClient<Dictionary<string, byte[]>>())
            {
                return tbl.ContainsKey(key) &&
                 ((System.Collections.Generic.Dictionary<string, byte[]>)tbl.Lists[key][0]).ContainsKey(valKey);
            }
        }

        public void Dispose()
        {
            _cacheManager.Dispose();
        }
    }

事實上,寫到這里,我們的redis方法簽名存儲就完成了,配合上一篇文章,你可以設計出自己的緩存系統了,在這里再多說一句,本緩存系統用到的設計模式類似於策略模式,它對於一個完善功能,可以多種實現的策略,而對外只公開一個標准的對象,其它具體

的,完整功能的實現都使用了internal作為修飾符,來對外界隱藏。

返回目錄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM