博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【BCVP更新】StackExchange.Redis 的异步开发方式
阅读量:4032 次
发布时间:2019-05-24

本文共 3839 字,大约阅读时间需要 12 分钟。

有哪些习惯

坚持

LESS IS MORE,SIMPLER IS BETTER THAN MORE

你一定会有很大的收获

各种小问题?

如果你之前用过Redis的话,肯定会使用过StackExchange.Redis,我之前很久就用过,在.netfw的时候,当时并发还比较小,没有什么问题,后来我就迁移到Blog.Core里了,但是有很多小伙伴,反馈高并发下,使用同步的方法会有问题,比如超时的问题,偶尔还会出现什么内存的问题,一直被很多网友所诟病。

一直说国内有一个组件很不错,这个大家自己去使用吧,我也不多说什么,但是我想着StackExchange.Redis既然是官方推荐的不会这么菜吧,果然官方给的方案是,用异步的方式写,会解决超时的问题。

那具体应该怎么写呢,我还没有来得及思考,正好这两天研究微软的微服务案例eShopOnContainers,我发现他就是用的StackExchange.Redis实现的购物车缓存的子服务逻辑,研究了下,迁移到Blog.Core项目中,当然我这里简单测试了下,并发下没有问题,大家还是可以自行测试,当然还是那句话,有问题了我会继续修改,如果还是不行,那自己就换其他的组件吧。

设计异步方案

这个比较简单的,设计思路和之前的是一样的,只不过有一点,连接调制器的注入方式我做了调整(ConnectionMultiplexer),之前用的是双if夹lock的方式,实现的单例,现在直接使用依赖注入AddSingleton的方式,更专业些,也没那么幺蛾子:

/// /// Redis缓存 启动服务/// public static class RedisCacheSetup{    public static void AddRedisCacheSetup(this IServiceCollection services)    {        if (services == null) throw new ArgumentNullException(nameof(services));        services.AddTransient
(); services.AddSingleton
(sp => { //获取连接字符串 string redisConfiguration = Appsettings.app(new string[] { "AppSettings", "RedisCachingAOP", "ConnectionString" });            var configuration = ConfigurationOptions.Parse(redisConfiguration, true);            configuration.ResolveDns = true; return ConnectionMultiplexer.Connect(configuration);        }); }}

这里是Redis依赖注入的扩展方法,需要在Startup里配置上,别忘记了:

services.AddRedisCacheSetup();

然后就是设计接口和实现类了,也很简单,接口和之前的一样,只不过都换成了异步:

///  /// Redis缓存接口 ///  public interface IRedisBasketRepository {     //获取 Reids 缓存值     Task
GetValue(string key); //获取值,并序列化 Task
Get
(string key); //保存 Task Set(string key, object value, TimeSpan cacheTime); //判断是否存在 Task
Exist(string key); //移除某一个缓存值 Task Remove(string key); //全部清除 Task Clear(); }

接口的名称我为了纪念eShop项目,保持一致了,虽然比较怪,自己酌情修改吧。

然后实现类也很简单,构造函数直接注入日志和连接调制器实例,不用写复杂的单例模式了:

public class RedisBasketRepository : IRedisBasketRepository {     private readonly ILogger
_logger; private readonly ConnectionMultiplexer _redis; private readonly IDatabase _database; public RedisBasketRepository(ILogger
logger, ConnectionMultiplexer redis) { _logger = logger; _redis = redis; _database = redis.GetDatabase(); } private IServer GetServer() { var endpoint = _redis.GetEndPoints(); return _redis.GetServer(endpoint.First()); } public async Task Clear() { foreach (var endPoint in _redis.GetEndPoints()) { var server = GetServer(); foreach (var key in server.Keys()) { await _database.KeyDeleteAsync(key); } } } public async Task
Exist(string key) { return await _database.KeyExistsAsync(key); } public async Task
GetValue(string key) { return await _database.StringGetAsync(key); } public async Task Remove(string key) { await _database.KeyDeleteAsync(key); } public async Task Set(string key, object value, TimeSpan cacheTime) { if (value != null) { //序列化,将object值生成RedisValue await _database.StringSetAsync(key, SerializeHelper.Serialize(value), cacheTime); } } public async Task
Get
(string key) { var value = await _database.StringGetAsync(key); if (value.HasValue) { //需要用的反序列化,将Redis存储的Byte[],进行反序列化 return SerializeHelper.Deserialize
(value); } else { return default(TEntity); } } }

相应的逻辑也很简单,我详细基本都能看得懂。

最后就是在BlogRedisCacheAOP.cs中,也要修改下,毕竟改成了异步,还是要注意的:

写到最后

九月马上就要到了,新的一年也快结束了,准备好迎接125天的2021年了么!希望新的一年,一起都好起来,大家也要趁着时间好好学学知识,因为我相信到时候肯定会有很多岗位,机会总是会留给有准备的人,相信我,相信你自己。

生活の艺术

转载地址:http://aezdi.baihongyu.com/

你可能感兴趣的文章
arm linux 生成火焰图
查看>>
jtag dump内存数据
查看>>
linux和windows内存布局验证
查看>>
linux config
查看>>
linux insmod error -1 required key invalid
查看>>
linux kconfig配置
查看>>
linux不同模块completion通信
查看>>
linux printf获得时间戳
查看>>
C语言位扩展
查看>>
linux dump_backtrace
查看>>
linux irqdebug
查看>>
git 常用命令
查看>>
linux位操作API
查看>>
snprintf 函数用法
查看>>
uboot.lds文件分析
查看>>
uboot start.s文件分析
查看>>
没有路由器的情况下,开发板,虚拟机Ubuntu,win10主机,三者也可以ping通
查看>>
本地服务方式搭建etcd集群
查看>>
安装k8s Master高可用集群
查看>>
忽略图片透明区域的事件(Flex)
查看>>