在<<asp.net core上使用Redis探索(1)>>中,我介紹了一個微軟官方實現Microsoft.Extensions.Caching.Redis的類庫,這次,我們使用微軟官方的Redis客戶端。 使用Nuget引入Microsoft.Extensions.Caching.Redis庫, ...
在<<asp.net core上使用Redis探索(1)>>中,我介紹了一個微軟官方實現Microsoft.Extensions.Caching.Redis的類庫,這次,我們使用微軟官方的Redis客戶端。
使用Nuget引入Microsoft.Extensions.Caching.Redis庫, 依賴項:
Microsoft.Extensions.Caching.Abstract
Microsoft.Extensions.Options
StackExchange.Redis.StrongName
原來Microsoft.Extensions.Caching.Redis其實就是封裝了StackExchange.redis,作為.net core平臺下的redis客戶端與redis通信的。
源碼地址:
https://github.com/aspnet/Caching/tree/dev/src/Microsoft.Extensions.Caching.Redis
源碼分析:
RedisCache繼承自IDistributeCache介面,該介面是Microsoft.Extensions.Caching.Distributed命名空間下的一個介面,主要就是封裝了Redis的一些最基本的操作,比如,Set, Get, Refresh, Remove.就是最基本的增刪改查。
RedisCache類中有一個用於同步的SemaphoreSlim類,該類是CLR中的同步遍歷的混合構造——內核模式和用戶模式的混合。該類除了顯式實現了IDistributedCache的所有方法外,還有一個重要的方法要說下,那就是Connect()方法:
1 private void Connect() 2 { 3 if (_cache != null) 4 { 5 return; 6 } 7 8 _connectionLock.Wait(); 9 try 10 { 11 if (_cache == null) 12 { 13 _connection = ConnectionMultiplexer.Connect(_options.Configuration); 14 _cache = _connection.GetDatabase(); 15 } 16 } 17 finally 18 { 19 _connectionLock.Release(); 20 } 21 }
該方法用於連接Redis伺服器,通過RedisCacheOptions這個類的屬性,來連接redis資料庫,源碼:
1 /// <summary> 2 /// Configuration options for <see cref="RedisCache"/>. 3 /// </summary> 4 public class RedisCacheOptions : IOptions<RedisCacheOptions> 5 { 6 /// <summary> 7 /// The configuration used to connect to Redis. 8 /// </summary> 9 public string Configuration { get; set; } 10 11 /// <summary> 12 /// The Redis instance name. 13 /// </summary> 14 public string InstanceName { get; set; } 15 16 RedisCacheOptions IOptions<RedisCacheOptions>.Value 17 { 18 get { return this; } 19 } 20 }
其中的Configuration屬性就是我們的一般在.config文件中配置redis連接語句的地方,隨後我們會講到應用。而InstanceName是什麼?繼續看源碼(RedisCache.cs文件):
private readonly RedisCacheOptions _options; public RedisCache(IOptions<RedisCacheOptions> optionsAccessor) { if (optionsAccessor == null) { throw new ArgumentNullException(nameof(optionsAccessor)); } _options = optionsAccessor.Value; // This allows partitioning a single backend cache for use with multiple apps/services. _instance = _options.InstanceName ?? string.Empty; }
可以看到,這個屬性是可以設置為空的,那麼它到底是什麼呢?這個就是我們在存儲redis的時候的首碼了,我們可以這麼這是Demo, 或者Demo:test等。
也就是說RedisCache類主要就是實現了IDistributedCache介面的所有方法,同時另外實現了Connect()方法用來連接redis,而這個的連接又是基於StackExchange.Redis(關於StackExchange.Redis請看 StackExchange.Redis通用封裝類分享 )的ConnectionMultiplexer。但是我們在大型項目中使用的redis隊列在RedisCache類中並沒有實現,但是,要知道整個asp.net-core都是可拓展的,我們可以基於RedisCache類再實現一個pub/sub方法用來做消息隊列。
最後使用asp.net-core預設的DI容器將RedisCache類註冊到框架中。RedisCacheServiceCollectionExtensions類源碼:
1 /// <summary> 2 /// Extension methods for setting up Redis distributed cache related services in an <see cref="IServiceCollection" />. 3 /// </summary> 4 public static class RedisCacheServiceCollectionExtensions 5 { 6 /// <summary> 7 /// Adds Redis distributed caching services to the specified <see cref="IServiceCollection" />. 8 /// </summary> 9 /// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param> 10 /// <param name="setupAction">An <see cref="Action{RedisCacheOptions}"/> to configure the provided 11 /// <see cref="RedisCacheOptions"/>.</param> 12 /// <returns>The <see cref="IServiceCollection"/> so that additional calls can be chained.</returns> 13 public static IServiceCollection AddDistributedRedisCache(this IServiceCollection services, Action<RedisCacheOptions> setupAction) 14 { 15 if (services == null) 16 { 17 throw new ArgumentNullException(nameof(services)); 18 } 19 20 if (setupAction == null) 21 { 22 throw new ArgumentNullException(nameof(setupAction)); 23 } 24 25 services.AddOptions(); 26 services.Configure(setupAction); 27 // .net core DI容器的使用無非就是在容器中實例化介面,而介面的的實例化,是通過實例化介面的派生類(即以介面為父類的子類)... 28 services.Add(ServiceDescriptor.Singleton<IDistributedCache, RedisCache>()); 29 30 return services; 31 } 32 }
在這裡我們基於IServiceCollection介面拓展出來了一個方法,該方法就是微軟官方為我們創建的基於Redis的實現了,在最後使用DI的三種方法的Singleton來實現IOC。那麼我們怎麼來使用呢?
引入完了Microsoft.Extensions.Caching.Redis之後,在Startup類中:
1 services.AddDistributedRedisCache(option => 2 { 3 option.Configuration = "123.207.96.138:6379, password=*****"; 4 option.InstanceName = ""; 5 });
個人的建議是給Redis設置一個密碼,要不然容易被攻擊。
接下來就是給Redis設置值了, 我們新建一個WebApi的程式,然後新建一個HomeController Api控制器
1 [Produces("application/json")] 2 [Route("api/[controller]")] 3 public class HomeController : Controller 4 { 5 // 通過構造函數註入,內置IOC容器實例化了之後,就可以通過介面對象來調用相應的函數了. 6 private readonly IDistributedCache _distributedCache; 7 8 public HomeController(IDistributedCache distributedCache) 9 { 10 _distributedCache = distributedCache; 11 } 12 13 [HttpGet] 14 public async Task<string> Get() 15 { 16 17 var cacheKey = "TheTime"; 18 19 //await _distributedCache.RemoveAsync(cacheKey); 20 21 var existingTime = _distributedCache.GetString(cacheKey); 22 if (!string.IsNullOrEmpty(existingTime)) 23 { 24 return "Fetched from cache : " + existingTime; 25 } 26 else 27 { 28 existingTime = DateTime.UtcNow.ToString(); 29 30 _distributedCache.SetString(cacheKey, existingTime); 31 return "Added to cache : " + existingTime; 32 } 33 } 34 }
代碼我就不運行了,親測能用。