這幾天在面試,這個關於Redis緩存的博客一直沒空寫,今天總算有點時間了。面試
從好久好久以前,我就一直想學Redis了,反正看到各大招聘網上都要求Redis,不學就太落後了。redis
一開始我是按微軟官網文檔那樣配置的,而後發現這也太簡單了,不止配置簡單,連使用都這麼簡單,簡單得有點過度。以下圖所示,它是基於IDistributedCache接口注入的數據庫
這麼簡單,怎麼玩,我連判斷某個key值存不存在都沒辦法。json
固然了。絕對不是這麼簡單的。更高級的用法以下,要引入Microsoft.Extensions.Caching.StackExchangeRedis包緩存
ConnectionMultiplexer connection = ConnectionMultiplexer.Connect("127.0.0.1:6379"); IDatabase cache = connection.GetDatabase(0); cache.HashSet("key", "hashKey", "value"); cache.SetAdd("key2", "value");
那要怎麼用在系統裏呢,固然直接使用IDatabase也能夠,但不夠優雅,並且我還想經過配置文件,來決定是否啓用Redis,若是不啓用的話,就使用MemoryCache。很是好。想法有了。app
先定義一個接口ICacheHelper,這是用來注入的接口,我暫時只定義了string類型跟hash類型的緩存方法測試
public interface ICacheHelper { bool Exists(string key); void Set<T>(string key, T value); T Get<T>(string key); void Delete(string key); void Expire(string key, DateTime dateTime); void Expire(string key, TimeSpan timeSpan); void HashSet(string key, string hashKey, object hashValue); T HashGet<T>(string key, string hashKey); bool HashExists(string key, string hashKey); void HashDelete(string key, string hashKey); }
而後用Redis實現這個接口,RedisCacheHelper類spa
/// <summary> /// Redis助手 /// </summary> public class RedisCacheHelper : ICacheHelper { public IDatabase _cache; private ConnectionMultiplexer _connection; private readonly string _instance; public RedisCacheHelper(RedisCacheOptions options, int database = 0) { _connection = ConnectionMultiplexer.Connect(options.Configuration); _cache = _connection.GetDatabase(database); _instance = options.InstanceName; } public bool Exists(string key) { return _cache.KeyExists(_instance + key); } public void Set<T>(string key, T value) { _cache.StringSet(_instance + key, CommonHelper.ObjectToJsonString(value)); } public T Get<T>(string key) { return CommonHelper.JsonStringToObject<T>(_cache.StringGet(_instance + key)); } public void Delete(string key) { _cache.KeyDelete(_instance + key); } public void Expire(string key, DateTime dateTime) { _cache.KeyExpire(_instance + key, dateTime); } public void Expire(string key, TimeSpan timeSpan) { _cache.KeyExpire(_instance + key, timeSpan); } public void HashSet(string key, string hashKey, object hashValue) { string value = CommonHelper.ObjectToJsonString(hashValue); _cache.HashSet(_instance + key, hashKey, value); } public T HashGet<T>(string key, string hashKey) { var value = _cache.HashGet(_instance + key, hashKey); return CommonHelper.JsonStringToObject<T>(value); } public object HashGet(string key, string hashKey, Type type) { var value = _cache.HashGet(_instance + key, hashKey); return CommonHelper.JsonStringToObject(value, type); } public bool HashExists(string key, string hashKey) { return _cache.HashExists(_instance + key, hashKey); } public void HashDelete(string key, string hashKey) { _cache.HashDelete(_instance + key, hashKey); } }
再用MemoryCache實現接口,MemoryCacheHelper類code
/// <summary> /// 緩存助手 /// </summary> public class MemoryCacheHelper : ICacheHelper { private readonly IMemoryCache _cache; public MemoryCacheHelper(IMemoryCache cache) { _cache = cache; } public bool Exists(string key) { return _cache.TryGetValue(key, out _); } public T Get<T>(string key) { return _cache.Get<T>(key); } public void Delete(string key) { _cache.Remove(key); } public void Set<T>(string key, T value) { _cache.Set(key, value); } public void Expire(string key, DateTime dateTime) { var value = _cache.Get(key); _cache.Set(key, value, dateTime); } public void Expire(string key, TimeSpan timeSpan) { var value = _cache.Get(key); _cache.Set(key, value, timeSpan); } public void HashSet(string key, string hashKey, object hashValue) { var hash = _cache.Get<Dictionary<string, object>>(key); if (hash.ContainsKey(hashKey)) { hash[key] = hashValue; } else { hash.Add(hashKey, hashValue); } _cache.Set<Dictionary<string, object>>(key, hash); } public T HashGet<T>(string key, string hashKey) { var hash = _cache.Get<Dictionary<string, object>>(key); if (hash.ContainsKey(hashKey)) { return (T)hash[hashKey]; } else { return default(T); } } public bool HashExists(string key, string hashKey) { var hash = _cache.Get<Dictionary<string, object>>(key); return hash.ContainsKey(hashKey); } public void HashDelete(string key, string hashKey) { var hash = _cache.Get<Dictionary<string, object>>(key); if (hash.ContainsKey(hashKey)) { hash.Remove(hashKey); } } }
實現類都有了,那如今就來實現根據配置值來決定是否使用Redis仍是MemoryCache,先在appsettings.json裏添加這個配置值,當Enable爲false時,就不啓用Redis,使用MemoryCache,Connection是Redis的鏈接字符串,InstanceName是緩存的前綴,Database是使用哪一個數據庫orm
"Redis": { "Enable": true, "Connection": "127.0.0.1:6379", "InstanceName": "LessSharp:", "Database": 0 }
再定義一個選項類 RedisOption
public class RedisOption { public bool Enable { get; set; } public string Connection { get; set; } public string InstanceName { get; set; } public int Database { get; set; } }
而後在Startup.cs類裏的ConfigureServices里根據配置值進行注入
var RedisConfiguration = Configuration.GetSection("Redis"); services.Configure<RedisOption>(RedisConfiguration); RedisOption redisOption = RedisConfiguration.Get<RedisOption>(); if (redisOption != null && redisOption.Enable) { var options = new RedisCacheOptions { InstanceName = redisOption.InstanceName, Configuration = redisOption.Connection }; var redis = new RedisCacheHelper(options, redisOption.Database); services.AddSingleton(redis); services.AddSingleton<ICacheHelper>(redis); } else { services.AddMemoryCache(); services.AddScoped<ICacheHelper, MemoryCacheHelper>(); }
OK,測試後完美