• 本地及远程二级缓存


    上周将本地缓存切换到远程缓存后,导致系统运行缓慢,经分析是一个页面反复读取缓存数据。Reveiw代码,发现是开发人员对缓存调用不够规范,导致循环调用缓存。

    代码遍布整个项目,修复成本较高,只能从底层的缓存框架解决。

    经构思,觉得在远程缓存基础上增加本地缓存,默认本地缓存超时6秒,这样基本解决一次请求,相同的缓存反复请求远程缓存问题,修改如下:

    1、请求缓存的时候,先请求本地缓存,如没有请求远程,远程有数据的时候,再本地缓存一份备份

    2、设置缓存的时候,同时设置本地和远程缓存

    3、省略本地缓存和远程缓存同步(因本地缓存设置过期时间非常短,只为了减少并发请求远程缓存,一般3-5秒左右)

    缓存接口:

        /// <summary>
        /// 缓存接口
        /// </summary>
        public interface ICache
        {
            /// <summary>
            /// 从缓存中取得指定键的值
            /// </summary>
            /// <param name="type">指定的类型</param>
            /// <param name="key">指定的键值</param>
            /// <returns></returns>
            object Get(Type type, string key);
            /// <summary>
            /// 从缓存中取得指定键的值
            /// </summary>
            /// <typeparam name="T">类型</typeparam>
            /// <param name="key">指定的键值</param>
            /// <returns>指定键值的值</returns>
            T Get<T>(string key);
    
            /// <summary>
            /// 从缓存中取出对象,如果没有缓存调用acquire方法
            /// </summary>
            /// <typeparam name="T">对象类型</typeparam>
            /// <param name="key">键值</param>
            /// <param name="acquire">如果缓存中没有对象的处理方法,处理方法</param>
            /// <param name="cacheTime">如果缓存中没有对象的处理方法设置缓存过期时间</param>
            /// <returns>指定键值的值</returns>
            T Get<T>(string key, Func<T> acquire, TimeSpan cacheTime);
    
            /// <summary>
            /// 从缓存中取出对象,如果没有缓存调用acquire方法
            /// </summary>
            /// <typeparam name="T">对象类型</typeparam>
            /// <param name="key">键值</param>
            /// <param name="acquire">如果缓存中没有对象的处理方法,处理方法</param>
            /// <param name="expiredTime">缓存绝对过期时间</param>
            /// <returns>指定键值的值</returns>
            T Get<T>(string key, Func<T> acquire, DateTime expiredTime);
    
            /// <summary>
            /// 从缓存中取出对象,如果没有缓存调用acquire方法
            /// </summary>
            /// <typeparam name="T">对象类型</typeparam>
            /// <param name="key">键值</param>
            /// <param name="acquire">如果缓存中没有对象的处理方法,处理方法</param>
            /// <param name="cacheExpiration">预先定义的缓存策略类型</param>
            /// <returns>指定键值的值</returns>
            T Get<T>(string key, Func<T> acquire, CacheExpirationTypes cacheExpiration);
    
            /// <summary>
            /// 添加一个对象到到缓存,使用缺省过期时间
            /// </summary>
            /// <param name="key">键值</param>
            /// <param name="data">存储到缓存中的对象</param>
            /// <param name="dependencyKeys">父键值</param>
            void Set(string key, object data, params string[] dependencyKeys);
    
            /// <summary>
            /// 添加一个对象到到缓存
            /// </summary>
            /// <param name="key">键值</param>
            /// <param name="data">存储到缓存中的对象</param>
            /// <param name="slidingTime">缓存时间</param>
            /// <param name="dependencyKeys">父键值</param>
            void Set(string key, object data, TimeSpan slidingTime, params string[] dependencyKeys);
    
            /// <summary>
            /// 添加一个绝对过期时间的对象到缓存
            /// </summary>
            /// <param name="key">缓存键值</param>
            /// <param name="data">缓存对象</param>
            /// <param name="expiredTime">绝对过期时间</param>
            /// <param name="dependencyKeys">父键值</param>
            void Set(string key, object data, DateTime expiredTime, params string[] dependencyKeys);
    
            /// <summary>
            /// 添加一个对象到到缓存
            /// </summary>
            /// <param name="key">键值</param>
            /// <param name="data">存储到缓存中的对象</param>
            /// <param name="cacheExpiration">缓存过期类型</param>
            /// <param name="dependencyKeys">父键值</param>
            void Set(string key, object data, CacheExpirationTypes cacheExpiration, params string[] dependencyKeys);
    
            /// <summary>
            /// 添加文件依赖对象到缓存
            /// </summary>
            /// <param name="key">键值</param>
            /// <param name="value">存储到缓存中的对象</param>
            /// <param name="dependencyFiles">依赖文件项</param>
            void SetFile(string key, object value, params string[] dependencyFiles);
    
            /// <summary>
            /// 添加文件依赖对象到缓存
            /// </summary>
            /// <param name="key">键值</param>
            /// <param name="value">存储到缓存中的对象</param>
            /// <param name="expiredTime">绝对过期时间</param>
            /// <param name="dependencyFiles">依赖文件项</param>
            void SetFile(string key, object value, DateTime expiredTime, params string[] dependencyFiles);
    
            /// <summary>
            /// 添加文件依赖对象到缓存
            /// </summary>
            /// <param name="key">键值</param>
            /// <param name="value">存储到缓存中的对象</param>
            /// <param name="slidingTime">缓存持续时间</param>
            /// <param name="dependencyFiles">依赖文件项</param>
            void SetFile(string key, object value, TimeSpan slidingTime, params string[] dependencyFiles);
    
            /// <summary>
            /// 判断是否已经缓存
            /// </summary>
            /// <param name="key">键值</param>
            /// <returns>是否存在</returns>
            bool IsSet(string key);
    
            /// <summary>
            /// 移除缓存
            /// </summary>
            /// <param name="key">键值</param>
            void Remove(string key);
    
            /// <summary>
            /// 按模式移除缓存
            /// </summary>
            /// <param name="pattern">正则表达式模式</param>
            void RemoveByPattern(string pattern);
    
            /// <summary>
            /// 清空缓存
            /// </summary>
            void Clear();
        }
    

    修改的Redis缓存Get方法

     1         /// <summary>
     2         /// 从缓存中取得指定键的值
     3         /// </summary>
     4         /// <typeparam name="T">类型</typeparam>
     5         /// <param name="key">指定的键值</param>
     6         /// <returns>指定键值的值</returns>
     7         public T Get<T>(string key)
     8         {
     9             key = GetKey(key);
    10             if (_useLocal)
    11             {
    12                 //先从本地获取缓存
    13                 var localValue = _localCache.Get(key);
    14                 if (localValue != null)
    15                 {
    16                     if (_debug)
    17                         Trace.WriteLine("Redis Cache Get from local:{0},Result:{1}".FormatWith(key, localValue.ToJson()));
    18 
    19                     return TypeConvert.ChangeType<T>(localValue);
    20                 }
    21             }
    22 
    23             Open();
    24             var value = _connection.Strings.GetString(_dbNumber, key);
    25             var jsonValue = _connection.Wait(value);
    26             Trace.WriteLine("get:{0},result:{1}".FormatWith(key, jsonValue));
    27             if (string.IsNullOrWhiteSpace(jsonValue))
    28             {
    29                 RemoveKeyDependency(key);
    30                 return default(T);
    31             }
    32 
    33             var cachedValue = jsonValue.FromJson<T>();
    34 
    35             if (_useLocal)
    36             {
    37                 //设置本地缓存
    38                 _localCache.Set(key, cachedValue, DateTime.Now + TimeSpan.FromSeconds(_defaultLocalExpiredTime));
    39             }
    40 
    41             return cachedValue;
    42         }
    View Code


    Set方法

     1         /// <summary>
     2         /// 添加一个对象到到缓存
     3         /// </summary>
     4         /// <param name="key">键值</param>
     5         /// <param name="data">存储到缓存中的对象</param>
     6         /// <param name="slidingTime">缓存时间</param>
     7         /// <param name="dependencyKeys"> </param>
     8         public void Set(string key, object data, TimeSpan slidingTime, params string[] dependencyKeys)
     9         {
    10             key = GetKey(key);
    11             if (data == null)
    12             {
    13                 Remove(key);
    14                 return;
    15             }
    16 
    17             if (_useLocal)
    18             {
    19                 //设置本地缓存
    20                 _localCache.Set(key, data,DateTime.Now + TimeSpan.FromSeconds(_defaultLocalExpiredTime));
    21             }
    22 
    23             Open();
    24             _connection.Strings.Set(_dbNumber, key, data.ToJson(), (long)slidingTime.TotalSeconds);
    25             Trace.WriteLine("Set:{0},value:{1}".FormatWith(key, data.ToJson()));
    26             if (dependencyKeys != null && dependencyKeys.Length > 0)
    27                 AddKeyDependency(key, dependencyKeys);
    28         }
    View Code

      

  • 相关阅读:
    Linux安装Nginx
    CentOS7上安装google谷歌浏览器
    解决MYSQL的错误:Got a packet bigger than 'max_allowed_packet' bytes
    Mysql ERROR 1067: Invalid default value for 字段
    Mysql查看版本号的五种方式介绍
    linux下mysql 查看默认端口号与修改端口号方法
    yum 和 rpm安装mysql彻底删除
    SpringBootSecurity学习(06)网页版登录方法级别的权限
    SpringBootSecurity学习(05)网页版登录内存中配置默认用户
    SpringBootSecurity学习(04)网页版登录其它授权和登录处理
  • 原文地址:https://www.cnblogs.com/keo2013/p/3334141.html
Copyright © 2020-2023  润新知