zoukankan      html  css  js  c++  java
  • Redis help class

    1. 先创建缓存接口

    /// <summary>
        /// 缓存接口
        /// </summary>
        public interface ICacheRepository : IDisposable
        {
            /// <summary>
            /// Get a cached item. If it's not in the cache yet, then load and cache it
            /// </summary>
            /// <typeparam name="T">Type of cached item</typeparam>
            /// <param name="key">Cache key</param>
            /// <param name="acquire">Function to load item if it's not in the cache yet</param>
            /// <returns>The cached value associated with the specified key</returns>
            T Get<T>(CacheKey key, Func<T> acquire) where T: class;
    
            /// <summary>
            /// Get a cached item. If it's not in the cache yet, then load and cache it
            /// </summary>
            /// <typeparam name="T">Type of cached item</typeparam>
            /// <param name="key">Cache key</param>
            /// <param name="acquire">Function to load item if it's not in the cache yet</param>
            /// <returns>The cached value associated with the specified key</returns>
            Task<T> GetAsync<T>(CacheKey key, Func<Task<T>> acquire) where T : class;
    
            /// <summary>
            /// Removes the value with the specified key from the cache
            /// </summary>
            /// <param name="key">Key of cached item</param>
            void Remove(CacheKey key);
    
            /// <summary>
            /// Adds the specified key and object to the cache
            /// </summary>
            /// <param name="key">Key of cached item</param>
            /// <param name="data">Value for caching</param>
            void Set(CacheKey key, object data);
    
            /// <summary>
            /// Gets a value indicating whether the value associated with the specified key is cached
            /// </summary>
            /// <param name="key">Key of cached item</param>
            /// <returns>True if item already is in cache; otherwise false</returns>
            bool IsSet(CacheKey key);
    
            /// <summary>
            /// Removes items by key prefix
            /// </summary>
            /// <param name="prefix">String key prefix</param>
            void RemoveByPrefix(string prefix);
    
            /// <summary>
            /// Clear all cache data
            /// </summary>
            void Clear();
        }

    2. redis类

    public class RedisCacheRepository : ICacheRepository
        {
            private bool _disposed;
            private readonly ILogger<RedisCacheRepository> _logger;
            private readonly ConnectionMultiplexer _redis;
            private readonly IDatabase _db;
            private readonly CacheOptions _cacheOptions;
    
            public RedisCacheRepository(
                ILogger<RedisCacheRepository> logger, 
                ConnectionMultiplexer redis, 
                IOptions<CacheOptions> cacheOptions)
            {
                _logger = logger;
                _redis = redis;
                _db = redis.GetDatabase();
                _cacheOptions = cacheOptions.Value;
            }
    
            #region Utilities
    
            /// <summary>
            /// Gets the list of cache keys prefix
            /// </summary>
            /// <param name="endPoint">Network address</param>
            /// <param name="prefix">String key pattern</param>
            /// <returns>List of cache keys</returns>
            protected virtual IEnumerable<RedisKey> GetKeys(EndPoint endPoint, string prefix = null)
            {
                var server = _redis.GetServer(endPoint);
    
                //we can use the code below (commented), but it requires administration permission - ",allowAdmin=true"
                //server.FlushDatabase();
    
                var keys = server.Keys(_db.Database, string.IsNullOrEmpty(prefix) ? null : $"{prefix}*");
    
                //we should always persist the data protection key list
                keys = keys.Where(key => !key.ToString().Equals(_cacheOptions.RedisDataProtectionKey,
                    StringComparison.OrdinalIgnoreCase));
    
                return keys;
            }
    
            /// <summary>
            /// Gets the value associated with the specified key.
            /// </summary>
            /// <typeparam name="T">Type of cached item</typeparam>
            /// <param name="key">Key of cached item</param>
            /// <returns>The cached value associated with the specified key</returns>
            protected virtual async Task<T> GetAsync<T>(CacheKey key) where T : class
            {
                //get serialized item from cache
                var serializedItem = await _db.StringGetAsync(key.Key);
                if (!serializedItem.HasValue)
                    return default;
    
                //deserialize item
                var item = JsonHelper.DeserializeJsonToObject<T>(serializedItem);
                if (item == null)
                    return default;
    
                return item;
            }
    
            /// <summary>
            /// Adds the specified key and object to the cache
            /// </summary>
            /// <param name="key">Key of cached item</param>
            /// <param name="data">Value for caching</param>
            /// <param name="cacheTime">Cache time in minutes</param>
            protected virtual async Task SetAsync(string key, object data, int cacheTime)
            {
                if (data == null)
                    return;
    
                //set cache time
                var expiresIn = TimeSpan.FromMinutes(cacheTime);
    
                //serialize item
                var serializedItem = JsonHelper.SerializeObject(data);
    
                //and set it to cache
                await _db.StringSetAsync(key, serializedItem, expiresIn);
            }
    
            /// <summary>
            /// Gets a value indicating whether the value associated with the specified key is cached
            /// </summary>
            /// <param name="key">Key of cached item</param>
            /// <returns>True if item already is in cache; otherwise false</returns>
            protected virtual async Task<bool> IsSetAsync(CacheKey key)
            {
                return await _db.KeyExistsAsync(key.Key);
            }
    
            /// <summary>
            /// Attempts to execute the passed function and ignores the RedisTimeoutException if specified by settings
            /// </summary>
            /// <typeparam name="T">Type of item which returned by the action</typeparam>
            /// <param name="action">The function to be tried to perform</param>
            /// <returns>(flag indicates whether the action was executed without error, action result or default value)</returns>
            protected virtual (bool, T) TryPerformAction<T>(Func<T> action)
            {
                try
                {
                    //attempts to execute the passed function
                    var rez = action();
    
                    return (true, rez);
                }
                catch (RedisTimeoutException)
                {
                    //ignore the RedisTimeoutException if specified by settings
                    if (_cacheOptions.IgnoreRedisTimeoutException)
                        return (false, default);
    
                    //or rethrow the exception
                    throw;
                }
            }
    
            #endregion
    
            #region Methods
    
            /// <summary>
            /// Get a cached item. If it's not in the cache yet, then load and cache it
            /// </summary>
            /// <typeparam name="T">Type of cached item</typeparam>
            /// <param name="key">Cache key</param>
            /// <param name="acquire">Function to load item if it's not in the cache yet</param>
            /// <returns>The cached value associated with the specified key</returns>
            public async Task<T> GetAsync<T>(CacheKey key, Func<Task<T>> acquire) where T: class
            {
                //item already is in cache, so return it
                if (await IsSetAsync(key))
                    return await GetAsync<T>(key);
    
                //or create it using passed function
                var result = await acquire();
    
                //and set in cache (if cache time is defined)
                if (key.CacheTime > 0)
                    await SetAsync(key.Key, result, key.CacheTime);
    
                return result;
            }
    
            /// <summary>
            /// Gets or sets the value associated with the specified key.
            /// </summary>
            /// <typeparam name="T">Type of cached item</typeparam>
            /// <param name="key">Key of cached item</param>
            /// <returns>The cached value associated with the specified key</returns>
            public virtual T Get<T>(CacheKey key) where T: class
            {
                var (_, rez) = TryPerformAction(() =>
                {
                    var serializedItem = _db.StringGet(key.Key);
                    if (!serializedItem.HasValue)
                        return default;
    
                    //deserialize item
                    var item = JsonHelper.DeserializeJsonToObject<T>(serializedItem);
                    return item ?? default;
                });
    
                return rez;
            }
    
            /// <summary>
            /// Get a cached item. If it's not in the cache yet, then load and cache it
            /// </summary>
            /// <typeparam name="T">Type of cached item</typeparam>
            /// <param name="key">Cache key</param>
            /// <param name="acquire">Function to load item if it's not in the cache yet</param>
            /// <returns>The cached value associated with the specified key</returns>
            public virtual T Get<T>(CacheKey key, Func<T> acquire) where T : class
            {
                //item already is in cache, so return it
                if (IsSet(key))
                {
                    var rez = Get<T>(key);
    
                    if (rez != null && !rez.Equals(default(T)))
                        return rez;
                }
    
                //or create it using passed function
                var result = acquire();
    
                //and set in cache (if cache time is defined)
                if (key.CacheTime > 0)
                    Set(key, result);
    
                return result;
            }
    
            /// <summary>
            /// Adds the specified key and object to the cache
            /// </summary>
            /// <param name="key">Key of cached item</param>
            /// <param name="data">Value for caching</param>
            public virtual void Set(CacheKey key, object data)
            {
                if (data == null)
                    return;
    
                //set cache time
                var expiresIn = TimeSpan.FromMinutes(key.CacheTime);
    
                //serialize item
                var serializedItem = JsonHelper.SerializeObject(data);
    
                //and set it to cache
                TryPerformAction(() => _db.StringSet(key.Key, serializedItem, expiresIn));
            }
    
            /// <summary>
            /// Gets a value indicating whether the value associated with the specified key is cached
            /// </summary>
            /// <param name="key">Key of cached item</param>
            /// <returns>True if item already is in cache; otherwise false</returns>
            public virtual bool IsSet(CacheKey key)
            {
                var (flag, rez) = TryPerformAction(() => _db.KeyExists(key.Key));
    
                return flag && rez;
            }
    
            /// <summary>
            /// Removes the value with the specified key from the cache
            /// </summary>
            /// <param name="key">Key of cached item</param>
            public virtual void Remove(CacheKey key)
            {
                //we should always persist the data protection key list
                if (key.Key.Equals(_cacheOptions.RedisDataProtectionKey, StringComparison.OrdinalIgnoreCase))
                    return;
                //remove item from caches
                TryPerformAction(() => _db.KeyDelete(key.Key));
            }
    
            /// <summary>
            /// Removes items by key prefix
            /// </summary>
            /// <param name="prefix">String key prefix</param>
            public virtual void RemoveByPrefix(string prefix)
            {
                foreach (var endPoint in _redis.GetEndPoints())
                {
                    var keys = GetKeys(endPoint, prefix);
    
                    TryPerformAction(() => _db.KeyDelete(keys.ToArray()));
                }
            }
    
            /// <summary>
            /// Clear all cache data
            /// </summary>
            public virtual void Clear()
            {
                foreach (var endPoint in _redis.GetEndPoints())
                {
                    var keys = GetKeys(endPoint).ToArray();
    
                    TryPerformAction(() => _db.KeyDelete(keys.ToArray()));
                }
            }
    
            /// <summary>
            /// Dispose cache manager
            /// </summary>
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
    
            // Protected implementation of Dispose pattern.
            protected virtual void Dispose(bool disposing)
            {
                if (_disposed)
                    return;
    
                _disposed = true;
            }
    
            #endregion
        }
    每天进步一点~~~ 如果你觉得本文对你有帮助,请点击“推荐”,如果想第一时间了解我的更新,请点击公告栏里的“+关注”,谢谢关注我的好友~!
  • 相关阅读:
    python命令行工具模块-click
    python项目代码打包成Docker镜像
    背包九讲
    秒杀项目的3个奇数问题:并发队列的选择,请求接口的合理设计,高并发下的数据安全
    java类加载过程
    索引失效
    java面试
    进程间通信
    HashMap在Jdk1.7和1.8中的实现
    十大排序算法
  • 原文地址:https://www.cnblogs.com/sunShineJing/p/15620383.html
Copyright © 2011-2022 走看看