在<
使用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 ///2 /// Configuration options for . 3 /// 4 public class RedisCacheOptions : IOptions 5 { 6 /// 7 /// The configuration used to connect to Redis. 8 /// 9 public string Configuration { get; set; } 10 11 /// 12 /// The Redis instance name. 13 /// 14 public string InstanceName { get; set; } 15 16 RedisCacheOptions IOptions .Value 17 { 18 get { return this; } 19 } 20 }
其中的Configuration属性就是我们的一般在.config文件中配置redis连接语句的地方,随后我们会讲到应用。而InstanceName是什么?继续看源码(RedisCache.cs文件):
private readonly RedisCacheOptions _options; public RedisCache(IOptionsoptionsAccessor) { 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 ///2 /// Extension methods for setting up Redis distributed cache related services in an . 3 /// 4 public static class RedisCacheServiceCollectionExtensions 5 { 6 /// 7 /// Adds Redis distributed caching services to the specified . 8 /// 9 /// The to add services to. 10 /// An to configure the provided 11 /// . 12 /// The so that additional calls can be chained. 13 public static IServiceCollection AddDistributedRedisCache(this IServiceCollection services, Action 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 ()); 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 }
代码我就不运行了,亲测能用。
百度云盘demo下载地址:
链接:https://pan.baidu.com/s/1vzuS5pEk_Ouh9I-NkPWXfg 密码:armw