zoukankan      html  css  js  c++  java
  • 【NET Core】 缓存 MemoryCache 和 Redis

     缓存接口 ICacheService

    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    
    namespace WebAppNetCore.Interface
    {
        public interface ICacheService
        {
            /// <summary>
            /// 验证缓存项是否存在
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <returns></returns>
            bool Exists(string key);
    
            /// <summary>
            /// 验证缓存项是否存在(异步方式)
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <returns></returns>
            Task<bool> ExistsAsync(string key);
    
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">缓存Value</param>
            /// <returns></returns>
            bool Add(string key, object value);
    
            /// <summary>
            /// 添加缓存(异步方式)
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">缓存Value</param>
            /// <returns></returns>
            Task<bool> AddAsync(string key, object value);
    
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">缓存Value</param>
            /// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
            /// <param name="expiressAbsoulte">绝对过期时长</param>
            /// <returns></returns>
            bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte);
    
            /// <summary>
            /// 添加缓存(异步方式)
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">缓存Value</param>
            /// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
            /// <param name="expiressAbsoulte">绝对过期时长</param>
            /// <returns></returns>
            Task<bool> AddAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte);
    
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">缓存Value</param>
            /// <param name="expiresIn">缓存时长</param>
            /// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
            /// <returns></returns>
            bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false);
    
            /// <summary>
            /// 添加缓存(异步方式)
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">缓存Value</param>
            /// <param name="expiresIn">缓存时长</param>
            /// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
            /// <returns></returns>
            Task<bool> AddAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false);
    
            /// <summary>
            /// 删除缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <returns></returns>
            bool Remove(string key);
    
            /// <summary>
            /// 删除缓存(异步方式)
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <returns></returns>
            Task<bool> RemoveAsync(string key);
    
            /// <summary>
            /// 批量删除缓存
            /// </summary>
            /// <param name="key">缓存Key集合</param>
            /// <returns></returns>
            void RemoveAll(IEnumerable<string> keys);
    
            /// <summary>
            /// 批量删除缓存(异步方式)
            /// </summary>
            /// <param name="key">缓存Key集合</param>
            /// <returns></returns>
            Task RemoveAllAsync(IEnumerable<string> keys);
    
            /// <summary>
            /// 获取缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <returns></returns>
            T Get<T>(string key) where T : class;
    
            /// <summary>
            /// 获取缓存(异步方式)
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <returns></returns>
            Task<T> GetAsync<T>(string key) where T : class;
    
            /// <summary>
            /// 获取缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <returns></returns>
            object Get(string key);
    
            /// <summary>
            /// 获取缓存(异步方式)
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <returns></returns>
            Task<object> GetAsync(string key);
    
            /// <summary>
            /// 获取缓存集合
            /// </summary>
            /// <param name="keys">缓存Key集合</param>
            /// <returns></returns>
            IDictionary<string, object> GetAll(IEnumerable<string> keys);
    
            /// <summary>
            /// 获取缓存集合(异步方式)
            /// </summary>
            /// <param name="keys">缓存Key集合</param>
            /// <returns></returns>
            Task<IDictionary<string, object>> GetAllAsync(IEnumerable<string> keys);
    
            /// <summary>
            /// 修改缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">新的缓存Value</param>
            /// <returns></returns>
            bool Replace(string key, object value);
    
            /// <summary>
            /// 修改缓存(异步方式)
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">新的缓存Value</param>
            /// <returns></returns>
            //Task<bool> ReplaceAsync(string key, object value);
    
            /// <summary>
            /// 修改缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">新的缓存Value</param>
            /// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
            /// <param name="expiressAbsoulte">绝对过期时长</param>
            /// <returns></returns>
            bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte);
    
            /// <summary>
            /// 修改缓存(异步方式)
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">新的缓存Value</param>
            /// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
            /// <param name="expiressAbsoulte">绝对过期时长</param>
            /// <returns></returns>
            //Task<bool> ReplaceAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte);
    
            /// <summary>
            /// 修改缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">新的缓存Value</param>
            /// <param name="expiresIn">缓存时长</param>
            /// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
            /// <returns></returns>
            bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false);
    
            /// <summary>
            /// 修改缓存(异步方式)
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">新的缓存Value</param>
            /// <param name="expiresIn">缓存时长</param>
            /// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
            /// <returns></returns>
            //Task<bool> ReplaceAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false);
        }
    }
    View Code

    缓存实现类 MemoryCacheService

    using Microsoft.Extensions.Caching.Memory;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using WebAppNetCore.Interface;
    
    namespace WebAppNetCore.Services
    {
        public class MemoryCacheService : ICacheService
        {
            protected IMemoryCache _cache;
            public MemoryCacheService(IMemoryCache cache)
            {
                _cache = cache;
            }
    
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">缓存Value</param>
            /// <returns></returns>
            public bool Add(string key, object value)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
                if (value == null)
                {
                    throw new ArgumentNullException(nameof(value));
                }
                _cache.Set(key, value);
                return Exists(key);
            }
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">缓存Value</param>
            /// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
            /// <param name="expiressAbsoulte">绝对过期时长</param>
            /// <returns></returns>
            public bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
                if (value == null)
                {
                    throw new ArgumentNullException(nameof(value));
                }
                _cache.Set(key, value,
                        new MemoryCacheEntryOptions()
                        .SetSlidingExpiration(expiresSliding)
                        .SetAbsoluteExpiration(expiressAbsoulte)
                        );
    
                return Exists(key);
            }
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">缓存Value</param>
            /// <param name="expiresIn">缓存时长</param>
            /// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
            /// <returns></returns>
            public bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
                if (value == null)
                {
                    throw new ArgumentNullException(nameof(value));
                }
                if (isSliding)
                    _cache.Set(key, value,
                        new MemoryCacheEntryOptions()
                        .SetSlidingExpiration(expiresIn)
                        );
                else
                    _cache.Set(key, value,
                    new MemoryCacheEntryOptions()
                    .SetAbsoluteExpiration(expiresIn)
                    );
    
                return Exists(key);
            }
            public Task<bool> AddAsync(string key, object value)
            {
                throw new NotImplementedException();
            }
    
            public Task<bool> AddAsync(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
            {
                throw new NotImplementedException();
            }
    
            public Task<bool> AddAsync(string key, object value, TimeSpan expiresIn, bool isSliding = false)
            {
                throw new NotImplementedException();
            }
    
            /// <summary>
            /// 验证缓存项是否存在
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <returns></returns>
            public bool Exists(string key)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
                object cached;
                return _cache.TryGetValue(key, out cached);
            }
    
            public Task<bool> ExistsAsync(string key)
            {
                throw new NotImplementedException();
            }
    
            /// <summary>
            /// 获取缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <returns></returns>
            public T Get<T>(string key) where T : class
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
                return _cache.Get(key) as T;
            }
            /// <summary>
            /// 获取缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <returns></returns>
            public object Get(string key)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
                return _cache.Get(key);
            }
            /// <summary>
            /// 获取缓存集合
            /// </summary>
            /// <param name="keys">缓存Key集合</param>
            /// <returns></returns>
            public IDictionary<string, object> GetAll(IEnumerable<string> keys)
            {
                if (keys == null)
                {
                    throw new ArgumentNullException(nameof(keys));
                }
    
                var dict = new Dictionary<string, object>();
    
                keys.ToList().ForEach(item => dict.Add(item, _cache.Get(item)));
    
                return dict;
            }
    
            public Task<IDictionary<string, object>> GetAllAsync(IEnumerable<string> keys)
            {
                throw new NotImplementedException();
            }
    
            public Task<T> GetAsync<T>(string key) where T : class
            {
                throw new NotImplementedException();
            }
    
            public Task<object> GetAsync(string key)
            {
                throw new NotImplementedException();
            }
    
            /// <summary>
            /// 删除缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <returns></returns>
            public bool Remove(string key)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
                _cache.Remove(key);
    
                return !Exists(key);
            }
            /// <summary>
            /// 批量删除缓存
            /// </summary>
            /// <param name="key">缓存Key集合</param>
            /// <returns></returns>
            public void RemoveAll(IEnumerable<string> keys)
            {
                if (keys == null)
                {
                    throw new ArgumentNullException(nameof(keys));
                }
    
                keys.ToList().ForEach(item => _cache.Remove(item));
            }
    
            public Task RemoveAllAsync(IEnumerable<string> keys)
            {
                throw new NotImplementedException();
            }
    
            public Task<bool> RemoveAsync(string key)
            {
                throw new NotImplementedException();
            }
    
            /// <summary>
            /// 修改缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">新的缓存Value</param>
            /// <returns></returns>
            public bool Replace(string key, object value)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
                if (value == null)
                {
                    throw new ArgumentNullException(nameof(value));
                }
                if (Exists(key))
                    if (!Remove(key)) return false;
    
                return Add(key, value);
    
            }
            /// <summary>
            /// 修改缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">新的缓存Value</param>
            /// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
            /// <param name="expiressAbsoulte">绝对过期时长</param>
            /// <returns></returns>
            public bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
                if (value == null)
                {
                    throw new ArgumentNullException(nameof(value));
                }
                if (Exists(key))
                    if (!Remove(key)) return false;
    
                return Add(key, value, expiresSliding, expiressAbsoulte);
            }
            /// <summary>
            /// 修改缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">新的缓存Value</param>
            /// <param name="expiresIn">缓存时长</param>
            /// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
            /// <returns></returns>
            public bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
                if (value == null)
                {
                    throw new ArgumentNullException(nameof(value));
                }
                if (Exists(key))
                    if (!Remove(key)) return false;
    
                return Add(key, value, expiresIn, isSliding);
            }
    
            public void Dispose()
            {
                if (_cache != null)
                    _cache.Dispose();
                GC.SuppressFinalize(this);
            }
        }
    }
    View Code

    缓存实现类 RedisCacheService

    using Microsoft.Extensions.Caching.Redis;
    using Newtonsoft.Json;
    using StackExchange.Redis;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using WebAppNetCore.Interface;
    
    namespace WebAppNetCore.Services
    {
        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;
            }
    
            /// <summary>
            /// 验证缓存项是否存在
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <returns></returns>
            public bool Exists(string key)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
                return _cache.KeyExists(GetKeyForRedis(key));
            }
    
    
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">缓存Value</param>
            /// <returns></returns>
            public bool Add(string key, object value)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
                return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)));
            }
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">缓存Value</param>
            /// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间,Redis中无效)</param>
            /// <param name="expiressAbsoulte">绝对过期时长</param>
            /// <returns></returns>
            public bool Add(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
                return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), expiressAbsoulte);
            }
            /// <summary>
            /// 添加缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">缓存Value</param>
            /// <param name="expiresIn">缓存时长</param>
            /// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间,Redis中无效)</param>
            /// <returns></returns>
            public bool Add(string key, object value, TimeSpan expiresIn, bool isSliding = false)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
    
    
                return _cache.StringSet(GetKeyForRedis(key), Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)), expiresIn);
            }
    
            /// <summary>
            /// 删除缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <returns></returns>
            public bool Remove(string key)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
                return _cache.KeyDelete(GetKeyForRedis(key));
            }
            /// <summary>
            /// 批量删除缓存
            /// </summary>
            /// <param name="key">缓存Key集合</param>
            /// <returns></returns>
            public void RemoveAll(IEnumerable<string> keys)
            {
                if (keys == null)
                {
                    throw new ArgumentNullException(nameof(keys));
                }
    
                keys.ToList().ForEach(item => Remove(item));
            }
    
            /// <summary>
            /// 获取缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <returns></returns>
            public T Get<T>(string key) where T : class
            {
                if (key == null)
                {
                    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">缓存Key</param>
            /// <returns></returns>
            public object Get(string key)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
    
                var value = _cache.StringGet(GetKeyForRedis(key));
    
                if (!value.HasValue)
                {
                    return null;
                }
                return JsonConvert.DeserializeObject(value);
            }
            /// <summary>
            /// 获取缓存集合
            /// </summary>
            /// <param name="keys">缓存Key集合</param>
            /// <returns></returns>
            public IDictionary<string, object> GetAll(IEnumerable<string> keys)
            {
                if (keys == null)
                {
                    throw new ArgumentNullException(nameof(keys));
                }
                var dict = new Dictionary<string, object>();
    
                keys.ToList().ForEach(item => dict.Add(item, Get(GetKeyForRedis(item))));
    
                return dict;
            }
    
    
    
            /// <summary>
            /// 修改缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">新的缓存Value</param>
            /// <returns></returns>
            public bool Replace(string key, object value)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
    
                if (Exists(key))
                    if (!Remove(key))
                        return false;
    
                return Add(key, value);
    
            }
            /// <summary>
            /// 修改缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">新的缓存Value</param>
            /// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
            /// <param name="expiressAbsoulte">绝对过期时长</param>
            /// <returns></returns>
            public bool Replace(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
    
                if (Exists(key))
                    if (!Remove(key))
                        return false;
    
                return Add(key, value, expiresSliding, expiressAbsoulte);
            }
            /// <summary>
            /// 修改缓存
            /// </summary>
            /// <param name="key">缓存Key</param>
            /// <param name="value">新的缓存Value</param>
            /// <param name="expiresIn">缓存时长</param>
            /// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
            /// <returns></returns>
            public bool Replace(string key, object value, TimeSpan expiresIn, bool isSliding = false)
            {
                if (key == null)
                {
                    throw new ArgumentNullException(nameof(key));
                }
    
                if (Exists(key))
                    if (!Remove(key)) return false;
    
                return Add(key, value, expiresIn, isSliding);
            }
    
            //这里我们写了个方法,来组合Key值和实例名,就是Key值转为 实例名+Key
            public string GetKeyForRedis(string key)
            {
                return _instance + key;
            }
    
            public void Dispose()
            {
                if (_connection != null)
                    _connection.Dispose();
                GC.SuppressFinalize(this);
            }
    
        }
    }
    View Code

    配置文件字段映射类

        public class AppsettingConfig
        {
            public string RedisConnection { get; set; }
    
            public string InstanceName { get; set; }
    
            public bool IsRedis { get; set; }
        }

    starup:

           public void ConfigureServices(IServiceCollection services)
            {
                //注入redis或者memorycache
                CacheInjection.Initialize(services, _appsettingConfig.RedisConnection,_appsettingConfig.InstanceName,_appsettingConfig.IsRedis); 
    }

    依赖注入

        public class CacheInjection
        {
            public static void Initialize(IServiceCollection services,string redisCon,string instanceName,bool isRedis = false)
            {
                //注册缓存服务
                services.AddMemoryCache();
                if (isRedis)
                {
                    //Use Redis
                    services.AddSingleton(typeof(ICacheService), new RedisCacheService(new RedisCacheOptions
                    {
                        Configuration = redisCon,
                        InstanceName = instanceName
                    }, 0));
                }
                else
                {
                    //Use MemoryCache
                    services.AddSingleton<IMemoryCache>(factory =>
                    {
                        var cache = new MemoryCache(new MemoryCacheOptions());
                        return cache;
                    });
                    services.AddSingleton<ICacheService, MemoryCacheService>();
                }
            }
        }

    参考文章:https://www.cnblogs.com/yuangang/p/5800113.html

  • 相关阅读:
    二维树状数组(模板)
    3033太鼓达人
    2503相框
    Ant Trip(画几笔)
    [ZJOI2004]嗅探器
    [USACO06JAN]冗余路径Redundant Paths(缩点)
    P3806 【模板】点分治1
    P4149 [IOI2011]Race
    P2634 [国家集训队]聪聪可可
    P4178 Tree
  • 原文地址:https://www.cnblogs.com/chuankang/p/8798826.html
Copyright © 2011-2022 走看看