首页 > 数据库 >CSRedisClient拿来主义,是这么用的吗?

CSRedisClient拿来主义,是这么用的吗?

时间:2023-07-20 12:37:28浏览次数:56  
标签:这么 缓存 InstanceName Controller 拿来主义 CSRedisClient new config

 

      开篇先引用下鲁迅先生笔下的《拿来主义》一说,暂且粗浅的理解为,拿来就用,以为是能达到自己想要的效果。

向鲁迅先生致敬!

     算是2021年的新项目吧,内部精心规划,来年招兵买马,注入了不少新鲜血液。新人或许有新气象。老人带领下的新团队,开启了老项目的重构计划...

新项目,名义上已DDD框架为设计原则,由于团队专业素质参差不齐,加之个人经验的影响,至今都不能说是一个清晰完整的DDD项目。业内,尤其是不同平台下的社区生态,架构到框架,理论到实践,总是能够

衍生出无数可能。这里我们暂且不吐糟这些不同认知及经验构建出来的框架,或许这样可能催生出璀璨的行业文化。

 

    时隔多年,到2023年,抽出一些时间,细看了下先前项目的源代码。脑海中只是隐约记得,总是有运营和用户反馈,某某页面,第一次加载总是很慢,连续刷新几次,也快不到那儿去。于是抽查了印象中的几个页面,

的确如此,首次很慢,几十个HTTP请求,1s以上的就接近10个。而问及这个问题时,开发者的表态,总是以单表数据太大,有关键词模糊等为由,不由分说了。粗略的看了下源代码,预感出,在多级缓存方面可能存在问题。项目中,有两种缓存,一种基于进程内IMemoryCache的方式,另一种,则是接入redis。

这里先不要断言,我们不能确保IMemoryCache的形式就不会有什么问题。于是基于此,创建了两个单元测试方法。一个是在调用较慢接口(HTTP请求耗时较长,一般超过1s的,从长到短),在这个过程中执行单元测试,

按步执行,在某些位置,的确出现了卡顿现象。首次出现卡顿的位置,就是使用IMemoryCache的地方。发现,开发者,无所顾忌的,读取了整表的数据,然后放入缓存,致使这个表在数据增多时,初次从数据库读取载入,

需要较长时间。那我们就先排除这个吧,注释掉这段,临时补上一段,继续。

     全文所说项目,乃是基于.net5、mysql、Redis、docker等这些技术栈为基础。

     发现,在请求HTTP的时,进入Controller的时间,明显超出预期。试想,应该是IOC在构建Controller时消耗了较长时间,导致我们发出请求,却迟迟没有进入Action。为了进一步验证是IOC构建Controller的过程出现了问题,

我尝试请求一个简单的接口,简单到不需要通过任何协议来获取数据的方法。事实证明,造成当前阶段卡顿的原因,不在接口,而在进入接口前,经历了什么。

    再进一步分析,分析Controller构造函数,注入了什么?注入的东西有没有依赖什么服务,比如redis。初步分析,依赖外部服务的有两种,第一个种,SqlSugarClient,第二种,CSRedisClient。那么我们继续进行第二个单元测试,

尝试分辨初始化依赖SqlSugarClient和CSRedisClient的服务,分析用时较长的一方。经分析,注入依赖CSRedisClient的地方,用时较长。由于项目引用的依赖CSRedisClient的组件,为当时团队开发,且nuget包上传至自建Nuget仓库中。

那我们就要进一步分析nuget包里的东西了。

        /// <summary>
        /// 创建缓存
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        private IDistributedCache CreateCache(RedisConfig config)
        {
   var _client = new CSRedisClient($"{config.ConnectionString},prefix={config.InstanceName},testcluster=false");
returnreturn new CSRedisCache(_client); }

看上面代码,他们是自定义了一个Cache类,内部通过这个方法,来创建IDistributedCache 对象。而且项目中依赖Cache类的服务,非单例,而是Score,这样致使每次请求,都会构建一个

CSRedisClient实例,而且初始化CSRedisClient的地方,的确有卡顿。改造下吧!
  /// <summary>
        /// <![CDATA[推荐,添加Redis单例服务]]>
        /// </summary>
        /// <param name="services"></param>
        /// <param name="func"></param>
        public static void AddRedisCacheSingletonService(this IServiceCollection services, Func<RedisConfig> func)
        {
            var config = func.Invoke();
            services.TryAddSingleton(new RedisConfig
            {
                ConnectionString = config.ConnectionString,
                InstanceName = config.InstanceName
            });
            services.TryAddSingleton<ICache, Cache>();
        }

来一个单例,使用CSRedisClient时推荐使用单例模式,不够用,考虑对象池吧。有时候,不需要CSRedisClient的方法,由于Service构造函数注入,不得不构建了。这里可考虑使用懒加载Layz<T>,用法也很简单,只有使用的时候,才会被初始化,

也就是在首次使用Layz Vaue时,就初始化了。后面同一个Lazy实例,访问Value仍是同一个实例,相当于缓存了Value。

       /// <summary>
        /// 创建缓存(延迟加载)
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        private Lazy<IDistributedCache> CreateCache(RedisConfig config)
        {
            return
                new Lazy<IDistributedCache>(() =>
                {
                    _client = new CSRedisClient($"{config.ConnectionString},prefix={config.InstanceName},testcluster=false");
                    return new CSRedisCache(_client);
                });
        }

经过两个地方的调整,接口响应时间从3s+,降低到了平均267ms。

 

      开篇先引用下鲁迅先生笔下的《拿来主义》一说,暂且粗浅的理解为,拿来就用,以为是能达到自己想要的效果。

 

     算是2021年的新项目吧,内部精心规划,来年招兵买马,注入了不少新鲜血液。新人或许有新气象。老人带领下的新团队,开启了老项目的重构计划...

新项目,名义上已DDD框架为设计原则,由于团队专业素质参差不齐,加之个人经验的影响,至今都不能说是一个清晰完整的DDD项目。业内,尤其是不同平台下的社区生态,架构到框架,理论到实践,总是能够

衍生出无数可能。这里我们暂且不吐糟这些不同认知及经验构建出来的框架,或许这样可能催生出璀璨的行业文化。

 

    时隔多年,到2023年,抽出一些时间,细看了下先前项目的源代码。脑海中只是隐约记得,总是有运营和用户反馈,某某页面,第一次加载总是很慢,连续刷新几次,也快不到那儿去。于是抽查了印象中的几个页面,

的确如此,首次很慢,几十个HTTP请求,1s以上的就接近10个。而问及这个问题时,开发者的表态,总是以单表数据太大,有关键词模糊等为由,不由分说了。粗略的看了下源代码,预感出,在多级缓存方面可能存在问题。项目中,有两种缓存,一种基于进程内IMemoryCache的方式,另一种,则是接入redis。

这里先不要断言,我们不能确保IMemoryCache的形式就不会有什么问题。于是基于此,创建了两个单元测试方法。一个是在调用较慢接口(HTTP请求耗时较长,一般超过1s的,从长到短),在这个过程中执行单元测试,

按步执行,在某些位置,的确出现了卡顿现象。首次出现卡顿的位置,就是使用IMemoryCache的地方。发现,开发者,无所顾忌的,读取了整表的数据,然后放入缓存,致使这个表在数据增多时,初次从数据库读取载入,

需要较长时间。那我们就先排除这个吧,注释掉这段,临时补上一段,继续。

 

     发现,在请求HTTP的时,进入Controller的时间,明显超出预期。试想,应该是IOC在构建Controller时消耗了较长时间,导致我们发出请求,却迟迟没有进入Action。为了进一步验证是IOC构建Controller的过程出现了问题,

我尝试请求一个简单的接口,简单到不需要通过任何协议来获取数据的方法。事实证明,造成当前阶段卡顿的原因,不在接口,而在进入接口前,经历了什么。

    再进一步分析,分析Controller构造函数,注入了什么?注入的东西有没有依赖什么服务,比如redis。初步分析,依赖外部服务的有两种,第一个种,SqlSugarClient,第二种,CSRedisClient。那么我们继续进行第二个单元测试,

尝试分辨初始化依赖SqlSugarClient和CSRedisClient的服务,分析用时较长的一方。经分析,注入依赖CSRedisClient的地方,用时较长。由于项目引用的依赖CSRedisClient的组件,为当时团队开发,且nuget包上传至自建Nuget仓库中。

那我们就要进一步分析nuget包里的东西了。

        /// <summary>
        /// 创建缓存
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        private IDistributedCache CreateCache(RedisConfig config)
        {
   var _client = new CSRedisClient($"{config.ConnectionString},prefix={config.InstanceName},testcluster=false");
returnreturn new CSRedisCache(_client); }

看上面代码,他们是自定义了一个Cache类,内部通过这个方法,来创建IDistributedCache 对象。而且项目中依赖Cache类的服务,非单例,而是Score,这样致使每次请求,都会构建一个

CSRedisClient实例,而且初始化CSRedisClient的地方,的确有卡顿。改造下吧!
  /// <summary>
        /// <![CDATA[推荐,添加Redis单例服务]]>
        /// </summary>
        /// <param name="services"></param>
        /// <param name="func"></param>
        public static void AddRedisCacheSingletonService(this IServiceCollection services, Func<RedisConfig> func)
        {
            var config = func.Invoke();
            services.TryAddSingleton(new RedisConfig
            {
                ConnectionString = config.ConnectionString,
                InstanceName = config.InstanceName
            });
            services.TryAddSingleton<ICache, Cache>();
        }

来一个单例,使用CSRedisClient时推荐使用单例模式,不够用,考虑对象池吧。有时候,不需要CSRedisClient的方法,由于Service构造函数注入,不得不构建了。这里可考虑使用懒加载Layz<T>,用法也很简单,只有使用的时候,才会被初始化,

也就是在首次使用Layz Vaue时,就初始化了。后面同一个Lazy实例,访问Value仍是同一个实例,相当于缓存了Value。

       /// <summary>
        /// 创建缓存(延迟加载)
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        private Lazy<IDistributedCache> CreateCache(RedisConfig config)
        {
            return
                new Lazy<IDistributedCache>(() =>
                {
                    _client = new CSRedisClient($"{config.ConnectionString},prefix={config.InstanceName},testcluster=false");
                    return new CSRedisCache(_client);
                });
        }

经过两个地方的调整,接口响应时间从3s+,降低到了平均267ms。

  好的东西,拿来就用的同时,有空请审视一下。

  至此,算是今天的随笔,算是告一段落。想来,已经快两年没有更新过博客了,到了饭点,各位干饭要紧!~

 



 

标签:这么,缓存,InstanceName,Controller,拿来主义,CSRedisClient,new,config
From: https://www.cnblogs.com/ibeisha/p/17567992.html

相关文章

  • 颠覆三观丨程序员原来可以这么帅
    《微微一笑很倾城》电影版一经上映,不仅在少男少女界们引起不错的反响,更是在苦逼程序员界掀起了巨大轰动!这电影太给程序员们长脸了。谁说程序员都是秃顶、谁说程序员都长得着急,谁说程序员常年呆若木鸡,谁说程序员的生活枯燥乏味!首先来感受一下什么叫做最帅码农,简直就是清风徐来,水波......
  • 小程序开发这么简单,还需要App吗?
    微信小程序自2017年推出以来,其生态系统得到了迅速的发展和壮大。作为中国最大的社交平台之一,微信拥有庞大的用户基础。微信小程序作为微信生态系统的一部分,自然而然地吸引了大量用户。据对公开资料进行统计,2021年全网小程序数量已超700万,其中微信小程序开发者突破300万,小程序DAU......
  • Redis为什么这么快之IO多路复用
    情景复现面试官:Redis为什么这么快?我:1.基于内存2.高效数据结构3.单线程4.IO多路复用面试官:那你讲讲Redis的IO多路复用模型是什么。我:哦,嗯,啊,呀...IO多路复用、文件描述符、用户态,内核态、哦。Redis的IO多路复用模型是什么I/O多路复用模型是什么?就是很多网络连接(多路),......
  • 19 | 为什么我只查一行的语句,也执行这么慢?
    以下内容出自《MySQL实战45讲》19|为什么我只查一行的语句,也执行这么慢?第一类:查询长时间不返回mysql>select*fromtwhereid=1;一般碰到这种情况。大概率是表t被锁住了。分析:首先执行showprocesslist命令,查看当前语句的状态。等MDL锁如上图,出现了......
  • 阿里架构师万字总结:Mybatis插件实现原理,Mybatis就要这么用
     mybatis中的插件,也就是拦截器interceptor,也挺有意思的。它的简单使用,就直接拿文档中的示例来简单说下一、使用使用方式很简单Copy//使用这个注解,表明这是一个拦截器@Intercepts(//方法签名{@Signature(//被拦截方法所在的类type=Executor.class......
  • 14 | count(*)这么慢,我该怎么办?
    一下内容出自《MySQL实战45讲》14|count(*)这么慢,我该怎么办?count(*)的实现方式不同的MySQL引擎中,count(*)有不同的实现方式。MyISAM引擎把一个表的总行数存在了磁盘上,执行count(*)的时候会直接返回这个数,效率很高;InnoDB引擎就执行count(*)的时候,需要把数......
  • 为什么面试官这么爱问性能优化?
     笔者是一个六年前端,没有大厂经历,也没有什么出彩的项目,所以今年以来,前端现在这种行情下并没有收到多少面试,但是为数不多的面试中,百分之九十都问到了性能优化的问题,而且问题都出奇的一致:平时的工作中你有做过什么性能优化?对于这个问题其实我的内心os是(各位轻喷~):你们怎么都这么爱问......
  • Java 网络爬虫,就是这么的简单
    是Java网络爬虫系列文章的第一篇,如果你还不知道Java网络爬虫系列文章,请参看学Java网络爬虫,需要哪些基础知识。第一篇是关于Java网络爬虫入门内容,在该篇中我们以采集虎扑列表新闻的新闻标题和详情页为例,需要提取的内容如下图所示: 我们需要提取图中圈出来的文字及其对......
  • 内容变现有了VVIP会员门槛,微博这么做图个啥?
    文|螳螂观察作者|易不二充分竞争的存量时代,用户是最宝贵的平台资产。这不仅体现在今年618期间,各大电商平台的“抢人大战”,更具体的风向还在于,作为移动互联网时代最有影响力的社交媒体之一,微博调整了新的会员体系。今年以来,微博已经多次做了产品调整。此次会员体系调整只是一个......
  • 学习C++就这么简单 ——《写给大家看的C++书》
    C++已经有很多年的历史了,虽然在它之后又出现了Java和C#之类的新语言,但它至今仍是人们开发软件时的最佳选择之一。那些巨头中的巨头,如微软、Adobe、英特尔、亚马逊、Google、苹果、诺基亚等公司,都在使用C++。这门语言相对比较容易使用(选用本书作为入门教材就更是如此了......