自从使用Asp.net Core2.0 以来,不停摸索,查阅资料,这方面的资料是真的少,因此,在前人的基础上,摸索出了Asp.net Core2.0 缓存 MemoryCache 和 Redis的用法,并实现了简单的封装
那么,先给出几个参考资料吧
关于两种缓存:https://www.cnblogs.com/yuangang/p/5800113.html
关于redis持久化:https://blog.csdn.net/u010785685/article/details/52366977
两个nuget包,不用多说
接下来,贴出代码
首先在startup,我读取了appstting.json的数据,作为redis的配置
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Application.Common; using Application.Common.CommonObject; using Application.CoreWork; using Application.DAL; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; namespace Application.web { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { Connection.MySqlConnection = Configuration.GetConnectionString("MySqlConnection"); Connection.SqlConnection = Configuration.GetConnectionString("SqlConnection"); RedisConfig.Connection = Configuration.GetSection("RedisConfig")["Connection"]; RedisConfig.DefaultDatabase =Convert.ToInt32( Configuration.GetSection("RedisConfig")["DefaultDatabase"]); RedisConfig.InstanceName = Configuration.GetSection("RedisConfig")["InstanceName"]; CommonManager.CacheObj.GetMessage<RedisCacheHelper>(); services.AddMvc(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseBrowserLink(); app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); } } }
再贴上配置
1
2
3
4
5
|
"RedisConfig" : { "Connection" : "127.0.0.1:6379" , "DefaultDatabase" : 0, "InstanceName" : "Redis1" }, |
用来放配置信息的静态类
using System; using System.Collections.Generic; using System.Text; namespace Application.Common { public static class RedisConfig { public static string configname { get; set; } public static string Connection { get; set; } public static int DefaultDatabase { get; set; } public static string InstanceName { get; set; } } }
然后ICacheHelper.cs,这个类是两种缓存通用的接口,让使用更方便
using System; using System.Collections.Generic; using System.Net; using System.Text; namespace Application.Common.CommonObject { public interface ICacheHelper { bool Exists(string key); T GetCache<T>(string key) where T : class; void SetCache(string key, object value); void SetCache(string key, object value, DateTimeOffset expiressAbsoulte);//设置绝对时间过期 void SetSlidingCache(string key, object value, TimeSpan t); //设置滑动过期, 因redis暂未找到自带的滑动过期类的API,暂无需实现该接口 void RemoveCache(string key); void KeyMigrate(string key, EndPoint endPoint,int database,int timeountseconds); void Dispose(); void GetMssages(); void Publish(string msg); } }
然后,实现接口,首先是MemoryCacheHelper
using Microsoft.Extensions.Caching.Memory; using System; using System.Collections.Generic; using System.Net; using System.Text; namespace Application.Common.CommonObject { public class MemoryCacheHelper : ICacheHelper { //public MemoryCacheHelper(/*MemoryCacheOptions options*/)//这里可以做成依赖注入,但没打算做成通用类库,所以直接把选项直接封在帮助类里边 //{ // //this._cache = new MemoryCache(options); // //this._cache = new MemoryCache(new MemoryCacheOptions()); //} //public MemoryCacheHelper(MemoryCacheOptions options)//这里可以做成依赖注入,但没打算做成通用类库,所以直接把选项直接封在帮助类里边 //{ // this._cache = new MemoryCache(options); //} public static IMemoryCache _cache=new MemoryCache(new MemoryCacheOptions()); /// <summary> /// 是否存在此缓存 /// </summary> /// <param name="key"></param> /// <returns></returns> public bool Exists(string key) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); object v = null; return _cache.TryGetValue<object>(key, out v); } /// <summary> /// 取得缓存数据 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public T GetCache<T>(string key) where T : class { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); T v = null; _cache.TryGetValue<T>(key, out v); return v; } /// <summary> /// 设置缓存 /// </summary> /// <param name="key"></param> /// <param name="value"></param> public void SetCache(string key, object value) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); if (value == null) throw new ArgumentNullException(nameof(value)); object v = null; if (_cache.TryGetValue(key, out v)) _cache.Remove(key); _cache.Set<object>(key, value); } /// <summary> /// 设置缓存,绝对过期 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="expirationMinute">间隔分钟</param> /// CommonManager.CacheObj.Save<RedisCacheHelper>("test", "RedisCache works!", 30); public void SetCache(string key, object value, double expirationMinute) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); if (value == null) throw new ArgumentNullException(nameof(value)); object v = null; if (_cache.TryGetValue(key, out v)) _cache.Remove(key); DateTime now = DateTime.Now; TimeSpan ts = now.AddMinutes(expirationMinute) - DateTime.Now; _cache.Set<object>(key, value, ts); } /// <summary> /// 设置缓存,绝对过期 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="expirationTime">DateTimeOffset 结束时间</param> /// CommonManager.CacheObj.Save<RedisCacheHelper>("test", "RedisCache works!", DateTimeOffset.Now.AddSeconds(30)); public void SetCache(string key, object value, DateTimeOffset expirationTime) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); if (value == null) throw new ArgumentNullException(nameof(value)); object v = null; if (_cache.TryGetValue(key, out v)) _cache.Remove(key); _cache.Set<object>(key, value, expirationTime); } /// <summary> /// 设置缓存,相对过期时间 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="t"></param> /// CommonManager.CacheObj.SaveSlidingCache<MemoryCacheHelper>("test", "MemoryCache works!",TimeSpan.FromSeconds(30)); public void SetSlidingCache(string key,object value,TimeSpan t) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); if (value == null) throw new ArgumentNullException(nameof(value)); object v = null; if (_cache.TryGetValue(key, out v)) _cache.Remove(key); _cache.Set(key, value, new MemoryCacheEntryOptions() { SlidingExpiration=t }); } /// <summary> /// 移除缓存 /// </summary> /// <param name="key"></param> public void RemoveCache(string key) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); _cache.Remove(key); } /// <summary> /// 释放 /// </summary> public void Dispose() { if (_cache != null) _cache.Dispose(); GC.SuppressFinalize(this); } public void KeyMigrate(string key, EndPoint endPoint, int database, int timeountseconds) { throw new NotImplementedException(); } public void GetMssages() { throw new NotImplementedException(); } public void Publish(string msg) { throw new NotImplementedException(); } } }
然后是RedisCacheHelper
using Microsoft.Extensions.Caching.Redis; using Newtonsoft.Json; using StackExchange.Redis; using System; using System.Collections.Generic; using System.Net; using System.Text; namespace Application.Common.CommonObject { public class RedisCacheHelper : ICacheHelper { public RedisCacheHelper(/*RedisCacheOptions options, int database = 0*/)//这里可以做成依赖注入,但没打算做成通用类库,所以直接把连接信息直接写在帮助类里 { options = new RedisCacheOptions(); options.Configuration = "127.0.0.1:6379";//RedisConfig.Connection; options.InstanceName = RedisConfig.InstanceName; int database = RedisConfig.DefaultDatabase; _connection = ConnectionMultiplexer.Connect(options.Configuration); _cache = _connection.GetDatabase(database); _instanceName = options.InstanceName; _sub = _connection.GetSubscriber(); } public static RedisCacheOptions options; public static IDatabase _cache; public static ConnectionMultiplexer _connection; public static string _instanceName; public static ISubscriber _sub; /// <summary> /// 取得redis的Key名称 /// </summary> /// <param name="key"></param> /// <returns></returns> private string GetKeyForRedis(string key) { return _instanceName + key; } /// <summary> /// 判断当前Key是否存在数据 /// </summary> /// <param name="key"></param> /// <returns></returns> public bool Exists(string key) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); return _cache.KeyExists(GetKeyForRedis(key)); } /// <summary> /// 取得缓存数据 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key"></param> /// <returns></returns> public T GetCache<T>(string key) where T : class { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); var value = _cache.StringGet(GetKeyForRedis(key)); if (!value.HasValue) return default(T); return JsonConvert.DeserializeObject<T>(value); } /// <summary> /// 设置缓存数据 /// </summary> /// <param name="key"></param> /// <param name="value"></param> public void SetCache(string key, object value) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); if (value == null) throw new ArgumentNullException(nameof(value)); if (Exists(GetKeyForRedis(key))) RemoveCache(GetKeyForRedis(key)); _cache.StringSet(GetKeyForRedis(key), JsonConvert.SerializeObject(value)); } /// <summary> /// 设置绝对过期时间 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="expiressAbsoulte"></param> public void SetCache(string key, object value, DateTimeOffset expiressAbsoulte) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); if (value == null) throw new ArgumentNullException(nameof(value)); if (Exists(GetKeyForRedis(key))) RemoveCache(GetKeyForRedis(key)); TimeSpan t = expiressAbsoulte - DateTimeOffset.Now; _cache.StringSet(GetKeyForRedis(key), JsonConvert.SerializeObject(value), t); } /// <summary> /// 设置相对过期时间 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="expirationMinute"></param> public void SetCache(string key, object value, double expirationMinute) { if (Exists(GetKeyForRedis(key))) RemoveCache(GetKeyForRedis(key)); DateTime now = DateTime.Now; TimeSpan ts = now.AddMinutes(expirationMinute) - now; _cache.StringSet(GetKeyForRedis(key), JsonConvert.SerializeObject(value), ts); } /// <summary> /// /// </summary> /// <param name="key"></param> /// <param name="endPoint"></param> /// <param name="database"></param> /// <param name="timeountseconds"></param> public void KeyMigrate(string key, EndPoint endPoint, int database, int timeountseconds) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); _cache.KeyMigrate(GetKeyForRedis(key), endPoint, database, timeountseconds); } /// <summary> /// 移除redis /// </summary> /// <param name="key"></param> public void RemoveCache(string key) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key)); _cache.KeyDelete(GetKeyForRedis(key)); } /// <summary> /// 销毁连接 /// </summary> public void Dispose() { if (_connection != null) _connection.Dispose(); GC.SuppressFinalize(this); } public void SetSlidingCache(string key, object value, TimeSpan t) { throw new NotImplementedException(); } public void GetMssages() { using (_connection = ConnectionMultiplexer.Connect(options.Configuration)) _sub.Subscribe("msg", (channel, message) => { string result = message; }); } public void Publish(string msg) { using (_connection=ConnectionMultiplexer.Connect(options.Configuration)) _sub.Publish("msg", msg); } } }
然后是Cache.cs,用来实例化,此处用单例模式,保证项目使用的是一个缓存实例,博主吃过亏,由于redis实例过多,构造函数运行太多次,导致client连接数过大,内存不够跑,速度卡慢
using System; using System.Collections.Generic; using System.Text; namespace Application.Common.CommonObject { public sealed class Cache { internal Cache() { } public static ICacheHelper cache; /// <summary> /// 判断缓存是否存在 /// </summary> /// <typeparam name="CacheType">缓存类型</typeparam> /// <param name="key">键名</param> /// <returns></returns> public bool Exists<CacheType>(string key) where CacheType : ICacheHelper, new() { if (cache!=null&& typeof(CacheType).Equals(cache.GetType())) return cache.Exists(key); else { cache = new CacheType(); return cache.Exists(key); } } /// <summary> /// 获取缓存 /// </summary> /// <typeparam name="T">转换的类</typeparam> /// <typeparam name="CacheType">缓存类型</typeparam> /// <param name="key">键名</param> /// <returns>转换为T类型的值</returns> public T GetCache<T,CacheType>(string key) where T:class where CacheType : ICacheHelper, new() { if (cache != null && typeof(CacheType).Equals(cache.GetType())) return cache.GetCache<T>(key); else { cache = new CacheType(); return cache.GetCache<T>(key); } } /// <summary> /// 保存缓存 /// </summary> /// <typeparam name="CacheType">缓存类型</typeparam> /// <param name="key">键名</param> /// <param name="value">值</param> public void Save<CacheType>(string key,object value) where CacheType : ICacheHelper, new() { if (cache != null && typeof(CacheType).Equals(cache.GetType())) cache.SetCache(key, value); else { cache = new CacheType(); cache.SetCache(key, value); } } /// <summary> /// 保存缓存并设置绝对过期时间 /// </summary> /// <typeparam name="CacheType">缓存类型</typeparam> /// <param name="key">键名</param> /// <param name="value">值</param> /// <param name="expiressAbsoulte">绝对过期时间</param> public void Save<CacheType>(string key, object value, DateTimeOffset expiressAbsoulte) where CacheType : ICacheHelper, new() { if (cache != null && typeof(CacheType).Equals(cache.GetType())) cache.SetCache(key, value, expiressAbsoulte); else { cache = new CacheType(); cache.SetCache(key, value, expiressAbsoulte); } } /// <summary> /// 保存滑动缓存 /// </summary> /// <typeparam name="CacheType">只能用memorycache,redis暂不实现</typeparam> /// <param name="key"></param> /// <param name="value"></param> /// <param name="t">间隔时间</param> public void SaveSlidingCache<CacheType>(string key, object value,TimeSpan t) where CacheType : MemoryCacheHelper, new() { if (cache != null && typeof(CacheType).Equals(cache.GetType())) cache.SetSlidingCache(key, value, t); else { cache = new CacheType(); cache.SetSlidingCache(key, value, t); } } /// <summary> /// 删除一个缓存 /// </summary> /// <typeparam name="CacheType">缓存类型</typeparam> /// <param name="key">要删除的key</param> public void Delete<CacheType>(string key)where CacheType : ICacheHelper, new() { if (cache != null && typeof(CacheType).Equals(cache.GetType())) cache.RemoveCache(key); else { cache = new CacheType(); cache.RemoveCache(key); } } /// <summary> /// 释放 /// </summary> /// <typeparam name="CacheType"></typeparam> public void Dispose<CacheType>() where CacheType : ICacheHelper, new() { if (cache != null && typeof(CacheType).Equals(cache.GetType())) cache.Dispose(); else { cache = new CacheType(); cache.Dispose(); } } public void GetMessage<CacheType>() where CacheType:RedisCacheHelper,new() { if (cache != null && typeof(CacheType).Equals(cache.GetType())) cache.GetMssages(); else { cache = new CacheType(); cache.GetMssages(); } } public void Publish<CacheType>(string msg)where CacheType : RedisCacheHelper, new() { if (cache != null && typeof(CacheType).Equals(cache.GetType())) cache.Publish(msg); else { cache = new CacheType(); cache.Publish(msg); } } } }
接下来,CommonManager.cs,该类主要是为了作为一个静态类调用缓存,由于Cache.cs并非静态类,方便调用
using Application.Common.CommonObject; using System; using System.Collections.Generic; using System.Text; namespace Application.Common { public class CommonManager { private static readonly object lockobj = new object(); private static volatile Cache _cache = null; /// <summary> /// Cache /// </summary> public static Cache CacheObj { get { if (_cache == null) { lock (lockobj) { if (_cache == null) _cache = new Cache(); } } return _cache; } } } }
最后呢就是使用啦随便建的一个控制器
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; using Application.Common; using Application.Common.CommonObject; using Application.CoreWork; using Microsoft.AspNetCore.Mvc; namespace Application.web.Controllers { public class DefaultController : BaseController { public IActionResult Index() { for (int i = 0; i < 100000; i++) { CommonManager.CacheObj.Save<RedisCacheHelper>("key" + i, "key" + i + " works!"); } return View(); } public IActionResult GetStrin(int index) { string res = "已经过期了"; if (CommonManager.CacheObj.Exists<RedisCacheHelper>("key" + index)) { res = CommonManager.CacheObj.GetCache<String, RedisCacheHelper>("key" + index); } return Json(new ExtJson { success = true, code = 1000, msg = "成功", jsonresult = res }); } public IActionResult Publish(string msg) { try { CommonManager.CacheObj.Publish<RedisCacheHelper>(msg); return Json(new ExtJson { success = true, code = 1000, msg = "成功", jsonresult = msg }); } catch { return Json(new ExtJson { success = true, code = 1000, msg = "失败", jsonresult = msg }); } } } }
那么,有的朋友在json处可能会报错,自己封装下,或者用原来的json吧
如果有不懂的地方,可以在评论中提问,有更好的改进方式,也请联系我,共同进步,感谢阅读