本地及远程二级缓存

上周将本地缓存切换到远程缓存后,导致系统运行缓慢,经分析是一个页面反复读取缓存数据。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

 

  

posted @ 2013-09-23 01:26  gzkeo  阅读(1794)  评论(2编辑  收藏  举报