您现在的位置是: 首页 > .NET CORE > 文章详情 文章详情
.net core Redis分布式缓存的客户端实现
2019-08-19 【.NET CORE】 1903人浏览
由于是基于.net-core平台,所以,我们最好是基于IDistributedCache接口来实现。ASP.NET-CORE下的官方redis客户端实现是基于StackExchange的。但是官方提供的IDistributeCache接口中的方法只是增删改查,我们可以继续拓展,增加订阅/发布,消息队列,当然这些方法必须是基于底层的StackExchange相对应的方法来做的。
如果我们要实现自己的Redis客户端,同时不使用底层的StackExchange驱动,可以派生一个继承自IDistributedCache的接口,定义自己需要的方法,例如:
public interface IServiceStackRedisCache : IDistributedCache{
void Delete(T item); // 删除
void DeleteAll(T item);
T Get(string id);
IQueryable GetAll();
IQueryable GetAll(string hash, string value);
IQueryable GetAll(string hash, string value, Expression> filter);
long PublishMessage(string channel, object item);
void Set(T item);
void Set(T item, List hash, List value, string keyName);
void Set(T item, string hash, string value, string keyName);
void SetAll(List listItems);
void SetAll(List list, List hash, List value, string keyName);
void SetAll(List list, string hash, string value, string keyName);}
接口有了,接下来就是继承自接口的类,我们定义一个类来实现接口里的方法,例如:
using ServiceStack.Redis;namespace Microsoft.Extensions.Caching.Redis{
public class ServiceStackRedisCache : IServiceStackRedisCache
{
private readonly IRedisClientsManager _redisManager;
private readonly ServiceStackRedisCacheOptions _options;
public ServiceStackRedisCache(IOptions optionsAccessor)
{
if (optionsAccessor == null)
{
throw new ArgumentNullException(nameof(optionsAccessor));
}
_options = optionsAccessor.Value;
var host = $"{_options.Password}@{_options.Host}:{_options.Port}";
RedisConfig.VerifyMasterConnections = false;
_redisManager = new RedisManagerPool(host);
}
#region Base
public byte[] Get(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
using (var client = _redisManager.GetClient() as IRedisNativeClient)
{
if (client.Exists(key) == 1)
{
return client.Get(key);
}
}
return null;
}
public async Task GetAsync(string key)
{
return Get(key);
}
public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
using (var client = _redisManager.GetClient() as IRedisNativeClient)
{
var expireInSeconds = GetExpireInSeconds(options);
if (expireInSeconds > 0)
{
client.SetEx(key, expireInSeconds, value);
client.SetEx(GetExpirationKey(key), expireInSeconds, Encoding.UTF8.GetBytes(expireInSeconds.ToString()));
}
else
{
client.Set(key, value);
}
}
}
public async Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options)
{
Set(key, value, options);
}
public void Refresh(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
using (var client = _redisManager.GetClient() as IRedisNativeClient)
{
if (client.Exists(key) == 1)
{
var value = client.Get(key);
if (value != null)
{
var expirationValue = client.Get(GetExpirationKey(key));
if (expirationValue != null)
{
client.Expire(key, int.Parse(Encoding.UTF8.GetString(expirationValue)));
}
}
}
}
}
public async Task RefreshAsync(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
Refresh(key);
}
public void Remove(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
using (var client = _redisManager.GetClient() as IRedisNativeClient)
{
client.Del(key);
}
}
public async Task RemoveAsync(string key)
{
Remove(key);
}
private int GetExpireInSeconds(DistributedCacheEntryOptions options)
{
if (options.SlidingExpiration.HasValue)
{
return (int)options.SlidingExpiration.Value.TotalSeconds;
}
else if (options.AbsoluteExpiration.HasValue)
{
return (int)options.AbsoluteExpirationRelativeToNow.Value.TotalSeconds;
}
else
{
return 0;
}
}
private string GetExpirationKey(string key)
{
return key + $"-{nameof(DistributedCacheEntryOptions)}";
}
#endregion
#region data
public T Get(string id)
{
using (var redisClient = _redisManager.GetClient())
{
var redis = redisClient.As();
return redis.GetById(id.ToLower());
}
}
public IQueryable GetAll()
{
using (var redisClient = _redisManager.GetClient())
{
var redis = redisClient.As();
return redis.GetAll().AsQueryable();
}
}
public IQueryable GetAll(string hash, string value, Expression> filter)
{
var filtered = _redisManager.GetClient().GetAllEntriesFromHash(hash).Where(c => c.Value.Equals(value, StringComparison.CurrentCultureIgnoreCase));
var ids = filtered.Select(c => c.Key);
var ret = _redisManager.GetClient().As().GetByIds(ids).AsQueryable()
.Where(filter);
return ret;
}
public IQueryable GetAll(string hash, string value)
{
var filtered = _redisManager.GetClient().GetAllEntriesFromHash(hash).Where(c => c.Value.Equals(value, StringComparison.CurrentCultureIgnoreCase));
var ids = filtered.Select(c => c.Key);
var ret = _redisManager.GetClient().As().GetByIds(ids).AsQueryable();
return ret;
}
public void Set(T item)
{
using (var redisClient = _redisManager.GetClient())
{
var redis = redisClient.As();
redis.Store(item);
}
}
public void Set(T item, string hash, string value, string keyName)
{
Type t = item.GetType();
PropertyInfo prop = t.GetProperty(keyName);
_redisManager.GetClient().SetEntryInHash(hash, prop.GetValue(item).ToString(), value.ToLower());
_redisManager.GetClient().As().Store(item);
}
public void Set(T item, List hash, List value, string keyName)
{
Type t = item.GetType();
PropertyInfo prop = t.GetProperty(keyName);
for (int i = 0; i ().Store(item);
}
public void SetAll(List listItems)
{
using (var redisClient = _redisManager.GetClient())
{
var redis = redisClient.As();
redis.StoreAll(listItems);
}
}
public void SetAll(List list, string hash, string value, string keyName)
{
foreach (var item in list)
{
Type t = item.GetType();
PropertyInfo prop = t.GetProperty(keyName);
_redisManager.GetClient().SetEntryInHash(hash, prop.GetValue(item).ToString(), value.ToLower());
_redisManager.GetClient().As().StoreAll(list);
}
}
public void SetAll(List list, List hash, List value, string keyName)
{
foreach (var item in list)
{
Type t = item.GetType();
PropertyInfo prop = t.GetProperty(keyName);
for (int i = 0; i ().StoreAll(list);
}
}
public void Delete(T item)
{
using (var redisClient = _redisManager.GetClient())
{
var redis = redisClient.As();
redis.Delete(item);
}
}
public void DeleteAll(T item)
{
using (var redisClient = _redisManager.GetClient())
{
var redis = redisClient.As();
redis.DeleteAll();
}
}
public long PublishMessage(string channel, object item)
{
var ret = _redisManager.GetClient().PublishMessage(channel, JsonConvert.SerializeObject(item));
return ret;
}
#endregion
}}
在这里我们使用ServiceStack来作为底层redis驱动。在构造函数中根据配置连接redis服务器。
aps.net-core给我们提供了强大的配置功能,使用强类型的Options,一般,我们实现一个继承自IOptions
然后我们在redis客户端类中(也就是上面的ServiceStackRedisCache类),使用构造函数注入。这样就能获取到redis的配置了。
然后我们在控制器的构造函数中注入redis客户端类实例:
private readonly IServiceStackRedisCache _cache;public ValuesController(IServiceStackRedisCache cache){
_cache = cache;}
如此,我们才能使用redis客户端去操作redis服务器。
最后就是最重要的部分了。ASP.NET-CORE框架随处可见的都是依赖注入。上面所有的程序,都是一个接口对应着一个类。所谓的依赖注入,其实就是继承自接口的类的实例化过程,但是这个过程是解耦的!DI的作用主要就是用来解耦实例化的过程。
ASP.NET-CORE框架依赖注入部分是在ConfigureService中使用的。
从上面的过程中,我们看到有两个构造函数的注入过程,因此,我们需要实现两个DI,分别是配置类的DI和redis客户端类的DI。
services.Configure(setupAction);services.Add(ServiceDescriptor.Singleton());
整个步骤就是:
1.定义接口,用于继承IDistributedCache的接口。该接口主要封装了基本的redis操作。
2.实现接口,实现redis的各个逻辑。
3.基于IOptions
4.在控制器的构造函数中注入。
5.依赖注入以上接口的实例。
完整demo下载: 链接:https://pan.baidu.com/s/17g3JQxdSBGJS2YoEaBxItw 密码:h60e
很赞哦! (1)
上一篇: 返回栏目列表
下一篇: .net core API 统一拦截错误
相关文章

热门收藏
- .net core Redis分布式缓存的客户端实现
- .net core API 统一拦截错误
- ASP.NET Core MVC中的IActionFilter.OnActionExecuted方法执行时,Controller中Action返回的对象是否已经输出到Http Response中
- aspnet core 2.1中使用jwt从原理到精通一
- aspnet core 2.1中使用jwt从原理到精通二
- aspnet core 2.1中使用jwt从原理到精通三
- ASP.NET Core 使用 JWT 搭建分布式无状态身份验证系统
- 消除 ASP.NET Core 告警 "No XML encryptor configured. Key may be persisted to storage in unencrypted form
- .NET Core 中基于 IHostedService 实现后台定时任务
- 【.Net Core】获取绝对路径、相对路径