Asp.net Core 缓存 MemoryCache 和 Redis

https://blog.csdn.net/warrior21st/article/details/62884629

缓存接口 ICacheService

 

   缓存也好,数据库也好,我们就是进行CRUD操作,接口没什么好解释的,注释我写的很明白,这里就列给大家:

 

  #  验证缓存项是否存在

 

复制代码

 1         /// 
 2         /// 验证缓存项是否存在
 3         /// 
 4         /// 缓存Key
 5         /// 
 6         bool Exists(string key);
 7 
 8         /// 
 9         /// 验证缓存项是否存在(异步方式)
10         /// 
11         /// 缓存Key
12         /// 
13         Task ExistsAsync(string key);  

复制代码

 

  # 添加缓存

 

复制代码

 1  /// 
 2         /// 添加缓存
 3         /// 
 4         /// 缓存Key
 5         /// 缓存Value
 6         /// 
 7         bool Add(string key, object value);
 8 
 9         /// 
10         /// 添加缓存(异步方式)
11         /// 
12         /// 缓存Key
13         /// 缓存Value
14         /// 
15         Task AddAsync(string key, object value);
16 
17         /// 
18         /// 添加缓存
19         /// 
20         /// 缓存Key
21         /// 缓存Value
22         /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)
23         /// 绝对过期时长
24         /// 
25         bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte);
26 
27         /// 
28         /// 添加缓存(异步方式)
29         /// 
30         /// 缓存Key
31         /// 缓存Value
32         /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)
33         /// 绝对过期时长
34         /// 
35         Task AddAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte);
36 
37         /// 
38         /// 添加缓存
39         /// 
40         /// 缓存Key
41         /// 缓存Value
42         /// 缓存时长
43         /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)
44         /// 
45         bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false);
46 
47         /// 
48         /// 添加缓存(异步方式)
49         /// 
50         /// 缓存Key
51         /// 缓存Value
52         /// 缓存时长
53         /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)
54         /// 
55         Task AddAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false);

复制代码

 

   # 删除缓存

 

复制代码

 1  /// 
 2         /// 删除缓存
 3         /// 
 4         /// 缓存Key
 5         /// 
 6         bool Remove(string key);
 7 
 8         /// 
 9         /// 删除缓存(异步方式)
10         /// 
11         /// 缓存Key
12         /// 
13         Task RemoveAsync(string key);
14 
15         /// 
16         /// 批量删除缓存
17         /// 
18         /// 缓存Key集合
19         /// 
20         void RemoveAll(IEnumerable keys);
21 
22         /// 
23         /// 批量删除缓存(异步方式)
24         /// 
25         /// 缓存Key集合
26         /// 
27         Task RemoveAllAsync(IEnumerable keys);

复制代码

 

     # 获取缓存

 

复制代码

 1 /// 
 2         /// 获取缓存
 3         /// 
 4         /// 缓存Key
 5         /// 
 6         T Get(string key) where T : class;
 7 
 8         /// 
 9         /// 获取缓存(异步方式)
10         /// 
11         /// 缓存Key
12         /// 
13         Task GetAsync(string key) where T : class;
14 
15         /// 
16         /// 获取缓存
17         /// 
18         /// 缓存Key
19         /// 
20         object Get(string key);
21 
22         /// 
23         /// 获取缓存(异步方式)
24         /// 
25         /// 缓存Key
26         /// 
27         Task GetAsync(string key);
28 
29         /// 
30         /// 获取缓存集合
31         /// 
32         /// 缓存Key集合
33         /// 
34         IDictionary GetAll(IEnumerable keys);
35 
36         /// 
37         /// 获取缓存集合(异步方式)
38         /// 
39         /// 缓存Key集合
40         /// 
41         Task> GetAllAsync(IEnumerable keys); 
  

复制代码

 

  # 修改缓存 

 

复制代码

 1 /// 
 2         /// 修改缓存
 3         /// 
 4         /// 缓存Key
 5         /// 新的缓存Value
 6         /// 
 7         bool Replace(string key, object value);
 8 
 9         /// 
10         /// 修改缓存(异步方式)
11         /// 
12         /// 缓存Key
13         /// 新的缓存Value
14         /// 
15         Task ReplaceAsync(string key, object value);
16 
17         /// 
18         /// 修改缓存
19         /// 
20         /// 缓存Key
21         /// 新的缓存Value
22         /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)
23         /// 绝对过期时长
24         /// 
25         bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte);
26 
27         /// 
28         /// 修改缓存(异步方式)
29         /// 
30         /// 缓存Key
31         /// 新的缓存Value
32         /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)
33         /// 绝对过期时长
34         /// 
35         Task ReplaceAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte);
36 
37         /// 
38         /// 修改缓存
39         /// 
40         /// 缓存Key
41         /// 新的缓存Value
42         /// 缓存时长
43         /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)
44         /// 
45         bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false);
46 
47         /// 
48         /// 修改缓存(异步方式)
49         /// 
50         /// 缓存Key
51         /// 新的缓存Value
52         /// 缓存时长
53         /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)
54         /// 
55         Task ReplaceAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false);

复制代码

 

 

缓存实现类 MemoryCache

 

  MemoryCache 这个比较简单,有微软比较完善的文档和一些比较好的文章,这个大家都用好久了。

  我们新建一个缓存实现类 MemoryCacheService 实现接口 ICacheService

  public class MemoryCacheService :ICacheService { }

  通过构造器注入 IMemoryCache:

  protected IMemoryCache _cache;

  public MemoryCacheService(IMemoryCache cache)
  {
    _cache = cache;
  }

  

  实现接口的方法,我们的方法都带有 异步 和 同步 两种,我们节约篇章和时间,异步的就不大家写了,大家自己添加一下就好。

 

  #  验证缓存项是否存在

  在MemoryCache中,我们是通过 TryGetValue 来检测 Key是否存在的

  

复制代码

 1 /// 
 2         /// 验证缓存项是否存在
 3         /// 
 4         /// 缓存Key
 5         /// 
 6         public bool Exists(string key)
 7         {
 8             if (key == null)
 9             {
10                 throw new ArgumentNullException(nameof(key));
11             }
12             object cached;
13             return _cache.TryGetValue(key,out cached);
14         }

复制代码

 

  # 添加缓存

  三个添加方法 :

  

复制代码

 1 /// 
 2         /// 添加缓存
 3         /// 
 4         /// 缓存Key
 5         /// 缓存Value
 6         /// 
 7         public bool Add(string key, object value)
 8         {
 9             if (key == null)
10             {
11                 throw new ArgumentNullException(nameof(key));
12             }
13             if (value == null)
14             {
15                 throw new ArgumentNullException(nameof(value));
16             }
17             _cache.Set(key, value);
18             return Exists(key);
19         }
20 /// 
21         /// 添加缓存
22         /// 
23         /// 缓存Key
24         /// 缓存Value
25         /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)
26         /// 绝对过期时长
27         /// 
28         public bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
29         {
30             if (key == null)
31             {
32                 throw new ArgumentNullException(nameof(key));
33             }
34             if (value == null)
35             {
36                 throw new ArgumentNullException(nameof(value));
37             }
38             _cache.Set(key, value,
39                     new MemoryCacheEntryOptions()
40                     .SetSlidingExpiration(expiresSliding)
41                     .SetAbsoluteExpiration(expiressAbsoulte)
42                     );
43 
44             return Exists(key);
45         }
46  /// 
47         /// 添加缓存
48         /// 
49         /// 缓存Key
50         /// 缓存Value
51         /// 缓存时长
52         /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)
53         /// 
54         public bool Add(string key, object value, TimeSpan expiresIn,bool isSliding = false)
55         {
56             if (key == null)
57             {
58                 throw new ArgumentNullException(nameof(key));
59             }
60             if (value == null)
61             {
62                 throw new ArgumentNullException(nameof(value));
63             }
64             if (isSliding)
65             _cache.Set(key, value,
66                 new MemoryCacheEntryOptions()
67                 .SetSlidingExpiration(expiresIn)
68                 );
69             else
70                 _cache.Set(key, value,
71                 new MemoryCacheEntryOptions()
72                 .SetAbsoluteExpiration(expiresIn)
73                 );
74 
75             return Exists(key);
76         }

复制代码

 

 

 

  # 删除缓存

  单个删除 和 批量删除

 

复制代码

 1 /// 
 2         /// 删除缓存
 3         /// 
 4         /// 缓存Key
 5         /// 
 6         public bool Remove(string key)
 7         {
 8             if (key == null)
 9             {
10                 throw new ArgumentNullException(nameof(key));
11             }
12             _cache.Remove(key);
13 
14             return !Exists(key);
15         }
16 /// 
17         /// 批量删除缓存
18         /// 
19         /// 缓存Key集合
20         /// 
21         public void RemoveAll(IEnumerable keys)
22         {
23             if (keys == null)
24             {
25                 throw new ArgumentNullException(nameof(keys));
26             }
27 
28             keys.ToList().ForEach(item => _cache.Remove(item));
29         }

复制代码

 

  # 获取缓存

 

复制代码

 1 /// 
 2         /// 获取缓存
 3         /// 
 4         /// 缓存Key
 5         /// 
 6         public T Get(string key) where T : class
 7         {
 8             if (key == null)
 9             {
10                 throw new ArgumentNullException(nameof(key));
11             }
12             return _cache.Get(key) as T;
13         }
14 /// 
15         /// 获取缓存
16         /// 
17         /// 缓存Key
18         /// 
19         public object Get(string key)
20         {
21             if (key == null)
22             {
23                 throw new ArgumentNullException(nameof(key));
24             }
25             return _cache.Get(key);
26         }
27 /// 
28         /// 获取缓存集合
29         /// 
30         /// 缓存Key集合
31         /// 
32         public IDictionary GetAll(IEnumerable keys)
33         {
34             if (keys == null)
35             {
36                 throw new ArgumentNullException(nameof(keys));
37             }
38 
39             var dict = new Dictionary();
40 
41             keys.ToList().ForEach(item => dict.Add(item, _cache.Get(item)));
42 
43             return dict;
44         }

复制代码

 

  # 修改缓存

复制代码

 1  /// 
 2         /// 修改缓存
 3         /// 
 4         /// 缓存Key
 5         /// 新的缓存Value
 6         /// 
 7         public bool Replace(string key, object value)
 8         {
 9             if (key == null)
10             {
11                 throw new ArgumentNullException(nameof(key));
12             }
13             if (value == null)
14             {
15                 throw new ArgumentNullException(nameof(value));
16             }
17             if (Exists(key))
18                 if (!Remove(key)) return false;
19 
20             return Add(key, value);
21 
22         }
23 /// 
24         /// 修改缓存
25         /// 
26         /// 缓存Key
27         /// 新的缓存Value
28         /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)
29         /// 绝对过期时长
30         /// 
31         public bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
32         {
33             if (key == null)
34             {
35                 throw new ArgumentNullException(nameof(key));
36             }
37             if (value == null)
38             {
39                 throw new ArgumentNullException(nameof(value));
40             }
41             if (Exists(key))
42                 if (!Remove(key)) return false;
43 
44             return Add(key, value, expiresSliding, expiressAbsoulte);
45         }
46 /// 
47         /// 修改缓存
48         /// 
49         /// 缓存Key
50         /// 新的缓存Value
51         /// 缓存时长
52         /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)
53         /// 
54         public bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false)
55         {
56             if (key == null)
57             {
58                 throw new ArgumentNullException(nameof(key));
59             }
60             if (value == null)
61             {
62                 throw new ArgumentNullException(nameof(value));
63             }
64             if (Exists(key))
65                 if (!Remove(key)) return false;
66 
67             return Add(key, value, expiresIn, isSliding);
68         }

复制代码

 

  最后 释放:

  public void Dispose()
  {
    if (_cache != null)
      _cache.Dispose();
    GC.SuppressFinalize(this);
  }

 

 

缓存实现类 Redis

 

  Redis一般都是运行的Liunx的,我们在 【(第十章)】发布项目到 Linux 上运行 Core 项目 中介绍了,如何在Linux上开发运行Core项目,当然,我相信,很多朋友还是在 Windows 上做开发、测试的,这里给大家一个windows 上的Redis和管理软件,如果没有或者不知道怎么找的朋友可以下载下来,在windows上测试 Redis :连接可能失效  百度网盘 提取码:uglb    百度网盘 提取码:gl0e

  安装第一个后,启动Redis服务就行了,管理软件的界面也很简洁

  Asp.net Core 缓存 MemoryCache 和 Redis_第1张图片

  Asp.net Core 缓存 MemoryCache 和 Redis_第2张图片

 

  我们先来看我们的 RedisCacheService:

  为了统一管理和切换使用,我们的 RedisCacheService 同样实现接口 ICacheService

  public class RedisCacheService : ICacheService { }

  同样,我们通过构造器注入:

  

  protected IDatabase _cache;

  private ConnectionMultiplexer _connection;

  private readonly string _instance;


  public RedisCacheService(RedisCacheOptions options, int database = 0)
  {
    _connection = ConnectionMultiplexer.Connect(options.Configuration);
    _cache = _connection.GetDatabase(database);
    _instance = options.InstanceName;
  }

  

  说明一下:我们需要添加一个Redis包:Microsoft.Extensions.Caching.Redis,这是官方的,但是不知道是我程序的原因还是什么原因,总是还原失败,命令强行还原包也不行,所以 我用的是移植的包: Microsoft.Extensions.Caching.Redis.Core,如果你们可以,最好还是用官方的包。

 

  这里我们写了个方法,来组合Key值和实例名,就是Key值转为 实例名+Key   

  public string GetKeyForRedis(string key)
  {
    return _instance + key;
  }

 

  # 验证缓存项是否存在

 

复制代码

 1 /// 
 2         /// 验证缓存项是否存在
 3         /// 
 4         /// 缓存Key
 5         /// 
 6         public bool Exists(string key)
 7         {
 8             if (key == null)
 9             {
10                 throw new ArgumentNullException(nameof(key));
11             }
12             return _cache.KeyExists(GetKeyForRedis(key));
13         }

复制代码

 

 

  # 添加缓存

 

  注意:我翻阅了很多资料,没有找到Redis支持滑动和绝对过期,但是都是继承的统一接口,所以这里添加方法 滑动过期时没有用的。

 

复制代码

 1 /// 
 2         /// 添加缓存
 3         /// 
 4         /// 缓存Key
 5         /// 缓存Value
 6         /// 
 7         public bool Add(string key, object value)
 8         {
 9             if (key == null)
10             {
11                 throw new ArgumentNullException(nameof(key));
12             }
13            return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)));
14         }
15 /// 
16         /// 添加缓存
17         /// 
18         /// 缓存Key
19         /// 缓存Value
20         /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间,Redis中无效)
21         /// 绝对过期时长
22         /// 
23         public bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
24         {
25             if (key == null)
26             {
27                 throw new ArgumentNullException(nameof(key));
28             }
29             return  _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)),expiressAbsoulte);
30         }
31 /// 
32         /// 添加缓存
33         /// 
34         /// 缓存Key
35         /// 缓存Value
36         /// 缓存时长
37         /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间,Redis中无效)
38         /// 
39         public bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false)
40         {
41             if (key == null)
42             {
43                 throw new ArgumentNullException(nameof(key));
44             }
45 
46 
47             return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), expiresIn);
48         }

复制代码

 

  # 删除缓存

 

复制代码

 1 /// 
 2         /// 删除缓存
 3         /// 
 4         /// 缓存Key
 5         /// 
 6         public bool Remove(string key)
 7         {
 8             if (key == null)
 9             {
10                 throw new ArgumentNullException(nameof(key));
11             }
12             return _cache.KeyDelete(GetKeyForRedis(key));
13         }
14 /// 
15         /// 批量删除缓存
16         /// 
17         /// 缓存Key集合
18         /// 
19         public void RemoveAll(IEnumerable keys)
20         {
21             if (keys == null)
22             {
23                 throw new ArgumentNullException(nameof(keys));
24             }
25 
26             keys.ToList().ForEach(item => Remove(item));
27         }

复制代码

 

  # 获取缓存

 

复制代码

 1 /// 
 2         /// 获取缓存
 3         /// 
 4         /// 缓存Key
 5         /// 
 6         public T Get(string key) where T : class
 7         {
 8             if (key == null)
 9             {
10                 throw new ArgumentNullException(nameof(key));
11             }
12 
13             var value = _cache.StringGet(GetKeyForRedis(key));
14 
15             if (!value.HasValue)
16             {
17                 return default(T);
18             }
19 
20             return JsonConvert.DeserializeObject(value);
21         }
22 /// 
23         /// 获取缓存
24         /// 
25         /// 缓存Key
26         /// 
27         public object Get(string key)
28         {
29             if (key == null)
30             {
31                 throw new ArgumentNullException(nameof(key));
32             }
33 
34             var value = _cache.StringGet(GetKeyForRedis(key));
35 
36             if(!value.HasValue)
37             {
38                 return null;
39             }
40 /// 
41         /// 获取缓存集合
42         /// 
43         /// 缓存Key集合
44         /// 
45         public IDictionary GetAll(IEnumerable keys)
46         {
47             if (keys == null)
48             {
49                 throw new ArgumentNullException(nameof(keys));
50             }
51             var dict = new Dictionary();
52 
53             keys.ToList().ForEach(item => dict.Add(item, Get(GetKeyForRedis(item))));
54 
55             return dict;
56         }
57 
58             return JsonConvert.DeserializeObject(value);
59         }

复制代码

 

  # 修改缓存

 

复制代码

 1 /// 
 2         /// 修改缓存
 3         /// 
 4         /// 缓存Key
 5         /// 新的缓存Value
 6         /// 
 7         public bool Replace(string key, object value)
 8         {
 9             if (key == null)
10             {
11                 throw new ArgumentNullException(nameof(key));
12             }
13 
14             if(Exists(key))
15                 if (!Remove(key))
16                     return false;
17 
18             return Add(key, value);
19 
20         }
21 /// 
22         /// 修改缓存
23         /// 
24         /// 缓存Key
25         /// 新的缓存Value
26         /// 滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)
27         /// 绝对过期时长
28         /// 
29         public bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
30         {
31             if (key == null)
32             {
33                 throw new ArgumentNullException(nameof(key));
34             }
35 
36             if (Exists(key))
37                 if (!Remove(key))
38                     return false;
39 
40             return Add(key, value, expiresSliding, expiressAbsoulte);
41         }
42 /// 
43         /// 修改缓存
44         /// 
45         /// 缓存Key
46         /// 新的缓存Value
47         /// 缓存时长
48         /// 是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)
49         /// 
50         public bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false)
51         {
52             if (key == null)
53             {
54                 throw new ArgumentNullException(nameof(key));
55             }
56 
57             if (Exists(key))
58                 if (!Remove(key)) return false;
59 
60             return Add(key, value, expiresIn, isSliding);
61         }

复制代码

 

  同样,释放:

  public void Dispose()
  {
    if (_connection != null)
      _connection.Dispose();
    GC.SuppressFinalize(this);
  }

 

Startup.cs 和 缓存配置

 

  我们在 【(第八章)】读取配置文件(二) 读取自定义配置文件 中讲到了如何读取自定义配置文件,同样,我们把缓存的配置 也放在 我们的自定义配置文件siteconfig.json中:

 

  Asp.net Core 缓存 MemoryCache 和 Redis_第3张图片

  

  我们写一个类,来获取配置几个配置:

  CacheProvider: _isUseRedis        --- 是否使用Redis

          _connectionString   --- Redis连接       

          _instanceName     ---Redis实例名称   

 

 

  在 Startup.cs 的 ConfigureServices(IServiceCollection services) 中:

 

  首先添加:services.AddMemoryCache();

  判断是否使用Redis,如果不使用 Redis就默认使用 MemoryCache:  

  if (_cacheProvider._isUseRedis)
  {
    //Use Redis
    services.AddSingleton(typeof(ICacheService), new RedisCacheService(new RedisCacheOptions
    {
      Configuration = _cacheProvider._connectionString,
      InstanceName = _cacheProvider._instanceName
    },0));
  }
  else
  {
    //Use MemoryCache
    services.AddSingleton(factory =>
    {
      var cache = new MemoryCache(new MemoryCacheOptions());
      return cache;
      });
    services.AddSingleton();
  }

 

  Asp.net Core 缓存 MemoryCache 和 Redis_第4张图片

 

你可能感兴趣的:(.Net,Core,Redis)