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 }
每天进步一点~~~
如果你觉得本文对你有帮助,请点击“推荐”,如果想第一时间了解我的更新,请点击公告栏里的“+关注”,谢谢关注我的好友~!