关系经济人类预测化学自然
自然科学
知识物理
化学生物
地理解释
预测理解
本质社会
人类现象
行为研究
经济政治
心理结构
关系指导
人文遗产

软件系统性能解决方案

3月15日 桃花醉投稿
  高性能设计会涉及到几个名词:IO多路复用、零拷贝、线程池、冗余等,其本质上是一个系统性的问题,可以从计算机体系结构的底层原来去思考,系统优化离不开CPU和IO两个维度,具体如下:如何设计高性能计算(CPU):减少计算成本,合理使用同步异步、限流减少请求次数等;让更多的核参与计算:多线程代替单线程、集群代替单机等等;如何提升系统IO:加快IO速度,顺序读写代替随机读写、硬件上SSD提升等;减少IO次数,索引分布式计算代替全表扫描、零拷贝减少IO复制次数、DB批量读写、分库分表增加连接数等;减少IO存储,数据过期策略、合理使用内存、缓存、DB等中间件,做好消息压缩等。方案一:计算性能优化
  1、减少程序计算复杂度循环遍历请求的requests,判断如果是A业务且A业务未达到终态返回false,否则返回truefor(Requetrequest:requests){1。queryDB获取TestDOStringidrequest。getId();TestDOtestDOqueryDOById(id);2。如果是A业务且testDO未到达中态记录为falseif(StringUtils。equals(A,request。getBizType())){check是否到达终态if(!StringUtils。equals(FINISHED,testDO。getStatus)){}}}
  代码中存在很明显的几个问题:
  1。每次请求过来在第6行都去查询DB,但是在第8行对请求做了判断和筛选,导致第6行的代码计算资源浪费,而且第6行访问DAO数据,是一个比较耗时的操作,可以先判断业务是否属于A再去查询DB;
  2。当前的需求是只要有一个A业务未到达终态即可返回false,11行可以在拿到false之后,直接break,减少计算次数;
  优化后的代码:循环遍历请求的requests,判断如果是A业务且A业务未达到终态返回false,否则返回truefor(Requetrequest:requests){1。不是A业务的不走查询DB的逻辑if(!StringUtils。equals(A,request。getBizType())){}2。queryDB获取TestDOStringidrequest。getId();TestDOtestDOqueryDOById(id);check是否到达终态if(!StringUtils。equals(FINISHED,testDO。getStatus)){}}
  优化之后的计算耗时从平均270。75ms40。5ms
  日常优化代码可以用ARTHAS工具分析下程序的调用耗时,耗时大的任务尽可能做好过滤,减少不必要的系统调用。
  2、合理使用同步异步
  分析业务链路中,哪些需要同步等待结果,哪些不需要,核心依赖的调度可以同步,非核心依赖尽量异步。
  场景:从链路上看A系统调用B系统,B系统调用C系统完成计算再把结论返回给A,A系统超时时间400ms,通常A系统调用B系统300ms,B系统调用C系统200ms。
  现在C系统需要将调用结论返回给D系统,耗时150ms
  此时A系统B系统C系统已有的调用链路可能会超时失败,因为引入D系统之后,耗时增加了150ms,整个过程是同步调用的,因此需要C系统将调用D系统更新结论的非强依赖改成异步调用。C系统调用D系统更新结果featureThreadPool。execute((){try{dSystemClient。updateResult(resultDTO);}catch(Exceptionexception){LogUtil。error(exception,logger,dSystemClient。updateResultfailed!resultDTO{0},JSON。toJSONString(resultDTO));}});
  3、做好限流保护
  故障场景:A系统调用B系统查询异常数据,日常10TPS左右甚至更少,某一天A系统改了定时任务触发逻辑,加上代码bug,调用频率达到了500TPS,并且由于ID传错,绕过了缓存直接查询了DB和Hbase,造成了Hbase读热点,拖垮集群,存储和查询都受到了影响。
  后续对A系统做了查询限流,保证并发量在15TPS以内,核心业务服务需要做好查询限流保护,同时也要做好缓存设计。
  4、多线程代替单线程
  场景:应急定位场景下,A系统调用B系统获取诊断结论,TR超时时间是500ms,对于一个异常ID事件,需要执行多个诊断项服务,并记录诊断流水;每个诊断的耗时大概在100ms以内,随着业务的增长,超过5个诊断项,计算耗时累加到500ms,这时候服务会出现高峰期短暂不可用。
  将这段代码改成异步执行,这样执行诊断的时间是耗时最大的诊断服务提交future任务并发执行futuresexecutor。invokeAll(tasks,timeout,timeUnit);遍历读取结果for(FutureResfuture:futures){try{获取结果RessingleResultfuture。get();if(singleResult!null){result。add(singleResult);}}catch(Exceptione){LogUtil。error(e,logger,并发执行发生异常!,poolName{0}。,threadPoolName);}}
  5、集群计算代替单机
  这里可以使用三层分发,将计算任务分片后执行,MapReduce思想,减少单机的计算压力。方案二:系统IO性能优化
  1、常见的FullGC解决
  系统常见的FullGC问题有很多,先讲一下JVM的垃圾回收机制:Heap区在设计上是分代设计的,划分为了Eden、Survivor和TenuredOld,其中Eden区、Survivor(存活)属于年轻代,TenuredOld区属于老年代或者持久代。一般我们将年轻代发生的GC称为MinorGC,对老年代进行GC称为MajorGC,FullGC是对整个堆来说。
  内存分配策略:1。对象优先在Eden区分配2。大对象直接进入老年代3。长期存活的对象将进入老年代4。动态对象年龄判定(虚拟机并不会永远地要求对象的年龄都必须达到MaxTenuringThreshold才能晋升老年代,如果Survivor空间中相同年龄的所有对象的大小总和大于Survivor的一半,年龄大于或等于该年龄的对象就可以直接进入老年代)5。只要老年代的连续空间大于(新生代所有对象的总大小或者历次晋升的平均大小)就会进行minorGC,否则会进行fullGC。
  系统常见触发FullGC的case:
  (1)查询大对象:业务上历史巡检数据需要定期清理,删除策略是每天删除上个月之前的数据(业务上打上软删除标记),等数据库定时清理任务彻底回收;
  某一天修改了删除策略,从删除上个月之前的数据改成了删除上周之前的数据,因此删除的数据从1000条膨胀到了15万条,数据对象占用了80以上的内存,直接导致系统的FullGC,其他任务都有影响;
  很多系统代码对于查询数据没有数量限制,随着业务的不断增长,系统容量在不升级的情况下,经常会查询出来很多大的对象List,出现大对象频繁GC的情况。
  (2)设置了用不回收的static方法
  A系统设置了static的List对象,本身是用来做DRM配置读取的,但是有个逻辑对配置信息做了查询之后,还进行了Put操作,导致随着业务的增长,static对象越来越大且属于类对象,无法回收,最终使得系统频繁GC。
  本身用Object做Map的Key有一定的不合理性,同时key中的对象是不可回收的,导致出现了GC。
  当执行FullGC后空间仍然不足,则抛出如下错误【java。lang。OutOfMemoryError:Javaheapspace】,而为避免以上两种状况引起的FullGC,调优时应尽量做到让对象在MinorGC阶段被回收、让对象在新生代多存活一段时间及不要创建过大的对象及数组。
  2、顺序读写代替随机读写
  对于普通的机械硬盘而言,随机写入的性能会很差,时间久了还会出现碎片,顺序的写入会极大节省磁盘寻址及磁盘盘片旋转的时间,极大提升性能;这层其实本身中间件帮我们实现了,比如Kafka的日志文件存储消息,就是通过有序写入消息和不可变性,消息追加到文件的末尾,来保证高性能读写。
  3、DB索引设计
  设计表结构时,我们要考虑后期对表数据的查询操作,设计合理的索引结构,一旦表索引建立好了之后,也要注意后续的查询操作,避免索引失效。
  (1)尽量不选择键值较少的列即区分度不明显,重复数据很少的做索引;比如我们用isdelete这种列做了索引,查询10万条数据,whereisdelete0,有9万条数据块,加上访问索引块带来的开销,不如全表扫描全部的数据块了;
  (2)避免使用前导like以及like,因为前面的匹配是模糊的,很难利用索引的顺序去访问数据块,导致全表扫描;但是使用likeA不影响,因为遇到B开头的数据就可以停止查找列,我们在做根据用户信息模糊查询数据时,遇到了索引失效的情况;
  (3)其他可能的场景比如,or查询,多列索引不使用第一部分查询,查询条件中有计算操作,或者全表扫描比索引查询更快的情况下也会出现索引失效;
  目前AntMonitor以及Tars等工具已经帮我们扫描出来耗时和耗CPU很大的SQL,可以根据执行计划调整查询逻辑,频繁的少量数据查询利用好索引,当然建立过多的索引也有存储开销,对于插入和删除很频繁的业务,也要考虑减少不必要的索引设计。
  4、分库分表设计
  随着业务的增长,如果集群中的节点数量过多,最终会达到数据库的连接限制,导致集群中的节点数量受限于数据库连接数,集群节点无法持续增加和扩容,无法应对业务流量的持续增长;这也是蚂蚁做LDC架构的其中原因之一,在业务层做水平拆分和扩展,使得每个单元的节点只访问当前节点对应的数据库。
  5、避免大量的表JOIN
  阿里编码规约中超过三个表禁止JOIN,因为三个表进行笛卡尔积计算会出现操作复杂度呈几何数增长,多个表JOIN时要确保被关联的字段有索引。
  如果为了业务上某些数据的级联,可以适当根据主键在内存中做嵌套的查询和计算,操作非常频繁的流水表建议对部分字段做冗余,以空间复杂度换取时间复杂度。
  6、减少业务流水表大量耗时计算
  业务记录有时候会做一些count操作,如果对时效性要求不高的统计和计算,建议定时任务在业务低峰期做好计算,然后将计算结果保存在缓存。
  涉及到多个表JOIN的建议采用离线表进行MapReduce计算,然后再将计算结果回流到线上表进行展示。
  7、数据过期策略
  一张表的数据量太大的情况下,如果不按照索引和日期进行部分扫描而出现全表扫描的情况,对DB的查询性能是非常有影响的,建议合理的设计数据过期策略,历史数据定期放入history表,或者备份到离线表中,减少线上大量数据的存储。
  8、合理使用内存
  众所周知,关系型数据库DB查询底层是磁盘存储,计算速度低于内存缓存,缓存DB与业务系统连接有一定的调用耗时,速度低于本地内存;但是从存储量来看,内存存储数据容量低于缓存,长期持久化的数据建议放DB存在磁盘中,设计过程中考虑好成本和查询性能的平衡。
  说到内存,就会有数据一致性问题,DB数据和内存数据如何保证一致性,是强一致性还是弱一致性,数据存储顺序和事务如何控制都需要去考虑,尽量做到用户无感知。
  9、做好数据压缩
  很多中间件对数据的存储和传输采用了压缩和解压操作,减少数据传输中的带宽成本,这里对数据压缩不再做过多的介绍,想提的一点是高并发的运行态业务,要合理的控制日志的打印,不能够为了便于排查,打印过多的JSON。toJSONString(Object),磁盘很容易被打满,按照日志的容量过期策略也很容易被回收,更不方便排查问题;因此建议合理的使用日志,错误码仅可能精简,核心业务逻辑打印好摘要日志,结构化的数据也便于后续做监控和数据分析。
  打印日志的时候思考几个问题:这个日志有没有可能会有人看,看了这个日志能做什么,每个字段都是必须打印的吗,出现问题能不能提高排查效率。
  10、Hbase热点key问题
  Habse的存储结构如下:Table在行的方向上分割为多个HRegion,HRegion是HBase中分布式存储和负载均衡的最小单元,即不同的HRegion可以分别在不同的HRegionServer上,但同一个HRegion是不会拆分到多个HRegionServer上的。HRegion按大小分割,每个表一般只有一个HRegion,随着数据不断插入表,HRegion不断增大,当HRegion的某个列簇达到一个阈值(默认256M)时就会分成两个新的HRegion。
  HBase中的行是按照Rowkey的字典顺序排序的,这种设计优化了scan操作,可以将相关的行以及会被一起读取的行存取在临近位置,便于scan。Rowkey这种固有的设计是热点故障的源头。热点的热是指发生在大量的client直接访问集群的一个或极少数个节点(访问可能是读,写或者其他操作)。
  大量访问会使热点Region所在的单个机器超出自身承受能力,引起性能下降甚至Region不可用,这也会影响同一个RegionServer上的其他Region,由于主机无法服务其他Region的请求,这样就造成数据热点(数据倾斜)现象。
  所以我们在向HBase中插入数据的时候,应优化RowKey的设计,使数据被写入集群的多个region,而不是一个,尽量均衡地把记录分散到不同的Region中去,平衡每个Region的压力。
  常见的热点Key避免的方法:反转,加盐和哈希反转:比如用户ID2088这种前缀,以及BBCRL开头的这种相同前缀,都可以适当的反转往后移动。加盐:RowKey的前面增加一些前缀,比如时间戳Hash,加盐的前缀种类越多,才会根据随机生成的前缀分散到各个region中,避免了热点现象,但是也要考虑scan方便哈希:为了在业务上能够完整地重构RowKey,前缀不可以是随机的。所以一般会拿原RowKey或其一部分计算Hash值,然后再对Hash值做运算作为前缀。
  总之Rowkey在设计的过程中,尽量保证长度原则、唯一原则、排序原则、散列原则。
搜索 投诉 评论 转载

超微信登顶AppStore榜首的啫喱下架,自称系统存卡顿等问2月13日晚间,啫喱App在其官方社交平台发布给用户的一封信称,最近几天,啫喱遭遇了连续的有组织的攻击,在各大平台被恶意造谣、在应用商店被水军刷差评。面对暗处庞大的势力,其坚决……售22。9万起综合续航超1000公里魏牌拿铁DHTPHEV正7月25日晚,魏牌旗下拿铁DHTPHEV车型正式上市,新车共推出3款配置车型,售价区间为22。926。3万元。新车基本上延续了拿铁DHT车型的外观设计,精致感十分到位,而由于有……北京纳凉好去处!11处绝美山川湖海,感受夏季惬意生活这些北京的山川湖海,一个赛着一个的漂亮!而且都是四季皆宜的好地方,不忙,您先收藏了!慢慢地去逛逛!01北京百瑞谷景区北京百瑞谷景区位于……刘诗雯新职位提前曝光!孙颖莎主管教练或换人,昔日旧主有望归化2022年成都世乒赛就要开始了,在最近各位主力球员,也都是悉数到达了比赛场地,可以说世乒赛对于每一位球员都非常的重要,譬如陈梦她如果能够拿下世乒赛的冠军,也可以实现自己大满贯的……鸡蛋是糖尿病的催化剂?研究结果公布,不妨提前了解糖尿病属于一种慢性代谢率的疾病,如果不加以控制的话,会容易引起一系列的并发症,对人们的生命健康构成很大的威胁。随着人们生活水平的改善,人们的饮食有了很大的变化,所以造成糖……这次的苏迪曼杯国羽虽然仍夺冠,但含金量水分不少苏迪曼杯是羽毛球界最高级别的混合团体赛,奇数年举办,中国队是卫冕冠军。而且此次夺冠后,中国队历史上一共连续十四次闯入决赛,获得了其中的十二次冠军。虽然此次的大比分是31,……山东推进农旅融合生态游成乡村振兴加速器游客在临沭县春山茶叶示范园体验游玩。临沭融媒供图中新网济南3月28日电(记者沙见龙)走进位于山东临沂市临沭县曹庄镇朱村现代农业示范园的草莓大棚,浓浓的草莓香扑面而来,绿油……越夜越yeah昌平这些夜经济消费地标,爱了为进一步激发消费需求鼓励夜间经济发展近日北京国际消费中心城市领导小组办公室发布《北京市促进夜间经济繁荣发展的若干措施》其中公布了24个夜京城融合消……胖的人容易饿,若进食量变得越来越多,当心是这3种疾病找上门提到肥胖二字,大家首先就会脑补出一个油腻的胖胖形象。在临床看来,超重虽然和遗传基因有关,但更多的就是受到了后天因素影响,长期吃的过多、营养过剩(习惯吃高热量、高脂肪、高糖……一个时代的终结!热火今天正式付清了波什的全部工资直播吧11月2日讯据《迈阿密先驱报》报道,热火今天向波什支付了他的最后一笔工资,正式付清了龙王的全部工资。2016年2月,波什被查出体内有血凝块,之后再未出战过。1617……软件系统性能解决方案高性能设计会涉及到几个名词:IO多路复用、零拷贝、线程池、冗余等,其本质上是一个系统性的问题,可以从计算机体系结构的底层原来去思考,系统优化离不开CPU和IO两个维度,具体如下……冬天最爱这早餐,比馒头香甜好吃,一蒸一卷上桌,清香低脂,特香莫愁厨路无知己,谁人不识小面姨。大家好,我是小面姨。今天小面姨给大家分享一道糯米豆沙卷的做法。这是一款大人小孩都喜欢吃的美食,软糯香甜,入口即化,吃在嘴里的感觉特别好。我家小孩……
激战鲁能,大连人要新仇旧恨一起算?外露精神,一外援划水东南亚王者最讨厌,烦人的5个辅助英雄詹俊那不勒斯已经横扫尤文,斯帕莱蒂真要夺得双冠了?小男孩发出一种声音,竟招来成群蚊子!专家正常太原人速看!收藏!开新能源车上路保险详情要知晓一个人是富贵命,还是贫穷命,就看他每天的生活习惯2022年骁龙870还是主力?iQOONeo6SE规格解析,春季的秦岭,春光醉人为什么现在的人都喜欢宇文成都,因为宇文成都对待士兵好宇宙那么大,为什么至今都不能发现外星人?或许有这些原因上海迪士尼将全面恢复运营!郑州5天打一场拔点清面的攻坚战古特雷斯已和普京通话,移除俄罗斯的这一障碍非常重要
空气炸锅炸薯条步骤空气炸锅怎么做薯条?香奈儿芭比粉是几号色应该是42号无疑了适合发说说的个性经典句子人,是活给自己看的【歌词】不凋谢的花歌手:动漫时代音乐茶座热传聚热点网 谁来守护银发时代中国雄起,挺你华为,华为刚刚拿下美国超级巨头回到原点心情语录公司债务需要哪些证据婆家用操蛋形容小孩调皮,我是真的不爱听,我该怎么说?吃什么补气补气的食物美媒中国希望新兴行业开发尖端技术,以防依赖西方创新办理经营许可证需要什么材料办理经营许可证需要哪些材料

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找菏泽德阳山西湖州宝鸡上海茂名内江三亚信阳长春北海西安安徽黄石烟台沧州湛江肇庆鹤壁六安韶关成都钦州