• 缓存篇~第七回 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作为修饰符,来对外界隐藏。

    返回目录

  • 相关阅读:
    linux中~和/的区别
    Linux centos 7安装
    xshell远程连接虚拟机
    虚拟机Linux不能上网简单有效的解决办法
    visudo
    users
    TreeSizeFree(硬盘文件整理)
    dos2unix
    iconv
    PS1系统变量
  • 原文地址:https://www.cnblogs.com/lori/p/4073290.html
Copyright © 2020-2023  润新知