分享好友 最新动态首页 最新动态分类 切换频道
(转)常见性能优化策略的总结
2024-12-27 13:06

转自美团技术博客,原文地址:https://mp.weixin.qq.com/s/67HR4e8mHcuOcPl4h7FEnQ

 

常见性能优化策略分类

 

之所以把代码放到第一位,是因为这一点最容易引起技术人员的忽视。很多技术人员拿到一个性能优化的需求以后,言必称缓存、异步、JVM等。实际上,第一步就应该是分析相关的代码,找出相应的瓶颈,再来考虑具体的优化策略。有一些性能问题,完全是由于代码写的不合理,通过直接修改一下代码就能解决问题的,比如for循环次数过多、作了很多无谓的条件判断、相同逻辑重复多次等。

 

数据库的调优,总的来说分为以下三部分:

 

这是最常用、每一个技术人员都应该掌握基本的SQL调优手段(包括方法、工具、辅助系统等)。这里以MySQL为例,最常见的方式是,由自带的慢查询日志或者开源的慢查询系统定位到具体的出问题的SQL,然后使用explain、profile等工具来逐步调优,最后经过测试达到效果后上线。这方面的细节,可以参考MySQL索引原理及慢查询优化。

 

这一类调优包括读写分离、多从库负载均衡、水平和垂直分库分表等方面,一般需要的改动较大,但是频率没有SQL调优高,而且一般需要DBA来配合参与。那么什么时候需要做这些事情?我们可以通过内部监控报警系统(比如Zabbix),定期跟踪一些指标数据是否达到瓶颈,一旦达到瓶颈或者警戒值,就需要考虑这些事情。通常,DBA也会定期监控这些指标值。

 

我们的应用为了实现数据库连接的高效获取、对数据库连接的限流等目的,通常会采用连接池类的方案,即每一个应用节点都管理了一个到各个数据库的连接池。随着业务访问量或者数据量的增长,原有的连接池参数可能不能很好地满足需求,这个时候就需要结合当前使用连接池的原理、具体的连接池监控数据和当前的业务量作一个综合的判断,通过反复的几次调试得到最终的调优参数。

 

本地缓存(HashMap/ConcurrentHashMap、Ehcache、Guava Cache等),缓存服务(Redis/Tair/Memcache等)。

 

什么情况适合用缓存?考虑以下两种场景:

 

什么时候更新缓存?如何保障更新的可靠性和实时性?

 

更新缓存的策略,需要具体问题具体分析。这里以门店POI的缓存数据为例,来说明一下缓存服务型的缓存更新策略是怎样的?目前约10万个POI数据采用了Tair作为缓存服务,具体更新的策略有两个:

 

缓存是否会满,缓存满了怎么办?

 

对于一个缓存服务,理论上来说,随着缓存数据的日益增多,在容量有限的情况下,缓存肯定有一天会满的。如何应对?

① 给缓存服务,选择合适的缓存逐出算法,比如最常见的LRU。

② 针对当前设置的容量,设置适当的警戒值,比如10G的缓存,当缓存数据达到8G的时候,就开始发出报警,提前排查问题或者扩容。

③ 给一些没有必要长期保存的key,尽量设置过期时间。

 

缓存是否允许丢失?丢失了怎么办?

 

根据业务场景判断,是否允许丢失。如果不允许,就需要带持久化功能的缓存服务来支持,比如Redis或者Tair。更细节的话,可以根据业务对丢失时间的容忍度,还可以选择更具体的持久化策略,比如Redis的RDB或者AOF。

 

缓存被“击穿”问题

 

对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑另外一个问题:缓存被“击穿”的问题。

 

针对某些客户端的请求,在服务端可能需要针对这些请求做一些附属的事情,这些事情其实用户并不关心或者用户不需要立即拿到这些事情的处理结果,这种情况就比较适合用异步的方式处理这些事情。

 

一种做法,是额外开辟线程,这里可以采用额外开辟一个线程或者使用线程池的做法,在IO线程(处理请求响应)之外的线程来处理相应的任务,在IO线程中让response先返回。

 

如果异步线程处理的任务设计的数据量非常巨大,那么可以引入阻塞队列BlockingQueue作进一步的优化。具体做法是让一批异步线程不断地往阻塞队列里扔数据,然后额外起一个处理线程,循环批量从队列里拿预设大小的一批数据,来进行批处理(比如发一个批量的远程服务请求),这样进一步提高了性能。

 

另一种做法,是使用消息队列(MQ)中间件服务,MQ天生就是异步的。一些额外的任务,可能不需要我这个系统来处理,但是需要其他系统来处理。这个时候可以先把它封装成一个消息,扔到消息队列里面,通过消息中间件的可靠性保证把消息投递到关心它的系统,然后让这个系统来做相应的处理。

 

比如C端在完成一个提单动作以后,可能需要其它端做一系列的事情,但是这些事情的结果不会立刻对C端用户产生影响,那么就可以先把C端下单的请求响应先返回给用户,返回之前往MQ中发一个消息即可。而且这些事情理应不是C端的负责范围,所以这个时候用MQ的方式,来解决这个问题最合适。

 

先说明一下,这里介绍的和缓存那一节不一样,虽然可能会使用一样的数据存储方案(比如Redis或者Tair),但是使用的方式不一样,这一节介绍的是把它作为DB来用。如果当作DB来用,需要有效保证数据存储方案的可用性、可靠性。

 

需要结合具体的业务场景,看这块业务涉及的数据是否适合用NoSQL来存储,对数据的操作方式是否适合用NoSQL的方式来操作,或者是否需要用到NoSQL的一些额外特性(比如原子加减等)。

 

如果业务数据不需要和其他数据作关联,不需要事务或者外键之类的支持,而且有可能写入会异常频繁,这个时候就比较适合用NoSQL(比如HBase)。

 

比如,美团点评内部有一个对exception做的监控系统,如果在应用系统发生严重故障的时候,可能会短时间产生大量exception数据,这个时候如果选用MySQL,会造成MySQL的瞬间写压力飙升,容易导致MySQL服务器的性能急剧恶化以及主从同步延迟之类的问题,这种场景就比较适合用Hbase类似的NoSQL来存储。

 

通过监控系统(如没有现成的系统,自己做一个简单的上报监控的系统也很容易)上对一些机器关键指标(gc time、gc count、各个分代的内存大小变化、机器的Load值与CPU使用率、JVM的线程数等)的监控报警,也可以看gc log和jstat等命令的输出,再结合线上JVM进程服务的一些关键接口的性能数据和请求体验,基本上就能定位出当前的JVM是否有问题,以及是否需要调优。

 

离线任务、异步任务、大数据任务、耗时较长任务的运行**,适当地利用,可达到加速的效果。

 

注意:线上对响应时间要求较高的场合,尽量少用多线程,尤其是服务线程需要等待任务线程的场合(很多重大事故就是和这个息息相关),如果一定要用,可以对服务线程设置一个最大等待时间。

 

如果单机的处理能力可以满足实际业务的需求,那么尽可能地使用单机多线程的处理方式,减少复杂性;反之,则需要使用多机多线程的方式。

 

对于单机多线程,可以引入线程池的机制,作用有二:

 

如果单机的处理能力不能满足需求,这个时候需要使用多机多线程的方式。这个时候就需要一些分布式系统的知识了。首先就必须引入一个单独的节点,作为调度器,其他的机器节点都作为执行器节点。调度器来负责拆分任务,和分发任务到合适的执行器节点;执行器节点按照多线程的方式(也可能是单线程)来执行任务。这个时候,我们整个任务系统就由单击演变成一个集群的系统,而且不同的机器节点有不同的角色,各司其职,各个节点之间还有交互。这个时候除了有多线程、线程池等机制,像RPC、心跳等网络通信调用的机制也不可少。后续我会出一个简单的分布式调度运行的框架。

 

严格来说,度量系统不属于性能优化的范畴,但是这方面和性能优化息息相关,可以说为性能优化提供一个强有力的数据参考和支撑。没有度量系统,基本上就没有办法定位到系统的问题,也没有办法有效衡量优化后的效果。很多人不重视这方面,但我认为它是系统稳定性和性能保障的基石。

 

如果要设计这套系统,总体来说有哪些关键流程需要设计呢?

① 确定指标
② 采集数据
③ 计算数据,存储结果
④ 展现和分析

 

按照需求出发,主要需要二方面的指标:

 

通常采用异步上报的方式,具体做法有两种:第一种,发到本地的Flume端口,由Flume进程收集到远程的Hadoop集群或者Storm集群来进行运算;第二种,直接在本地运算好以后,使用异步和本地队列的方式,发送到监控服务器。

 

可以采用离线运算(MapReduce/Hive)或者实时/准实时运算(Storm/Spark)的方式,运算后的结果存入MySQL或者HBase;某些情况,也可以不计算,直接采集发往监控服务器。

 

提供统一的展现分析平台,需要带报表(列表/图表)监控和报警的功能。

真实案例分析

 

这是一个每小时定期运行一次的job,作用是用来刷新商家与控制区的关系。具体规则就是根据商家的配送范围(多个)与控制区是否有交集,如果有交集,就把这个商家划到这个控制区的范围内。

 

需要这个过程越短越好,最好保持在20分钟内。

 

原有代码的主要处理流程是:

 

分析代码,发现第2步的a步骤和b步骤,找出和某控制区相交的配送范围集合并对商家ID去重,可以采用R树空间索引的方式来优化。具体做法是:

 

这个优化已经在第一期优化中上线,整个过程耗时由40多分钟缩短到20分钟以内。

 

第一期优化改为R树以后,运行了一段时间,随着数据量增大,性能又开始逐渐恶化,一个月后已经恶化到50多分钟。于是继续深入代码分析,寻找了两个优化点,安排第二期优化并上线。

 

这两个优化点是:

 

通过日志观察,执行时间由50多分钟缩短到15分钟以内,下图是截取了一天的4台机器的日志时间(单位:毫秒):

可以看到,效果还是非常明显的。

 

2014年Q4,数据库中关于POI(这里可以简单理解为外卖的门店)相关的数据的读流量急剧上升,虽然说加入从库节点可以解决一部分问题,但是毕竟节点的增加是会达到极限的,达到极限后主从复制会达到瓶颈,可能会造成数据不一致。所以此时,急需引入一种新的技术方案来分担数据库的压力,降低数据库POI相关数据的读流量。另外,任何场景都考虑加DB从库的做法,会对资源造成一定的浪费。

 

基于已有的经过考验的技术方案,我选择Tair来作为缓存的存储方案,来帮DB分担来自于各应用端的POI数据的读流量的压力。理由主要是从可用性、高性能、可扩展性、是否经过线上大规模数据和高并发流量的考验、是否有专业运维团队、是否有成熟工具等几个方面综合考量决定。

 

第一版设计

 

缓存的更新策略,根据业务的特点、已有的技术方案和实现成本,选择了用MQ来接收POI改变的消息来触发缓存的更新,但是这个过程有可能失败;同时启用了key的过期策略,并且调用端会先判断是否过期,如过期,会从后端DB加载数据并回设到缓存,再返回。通过两个方面双保险确保了缓存数据的可用。

 

第二版设计

 

第一版设计运行到一段时间以后,我们发现了两个问题:

 

为了解决上述问题,我们从美团点评负责基础架构的同事那里了解到Databus可以解决缓存数据在某些情况下不一致的问题,并且可以去掉过期时间机制,从而提高查询效率,避免tair在内存不命中时查询硬盘。而且为了防止DataBus单点出现故障影响我们的业务,我们保留了之前接MQ消息更新缓存的方案,作了切换开关,利用这个方案作容错,整体架构如下:

 

 

上线后,通过持续地监控数据发现,随着调用量的上升,到DB的流量有了明显地减少,极大地减轻了DB的压力。同时这些数据接口的响应时间也有了明显地减少。缓存更新的双重保障机制,也基本保证了缓存数据的可用。见下图:

 

 

随着业务的快速发展,带来的访问量和数据量的急剧上升,通过我们相应的监控系统可以发现,系统的某些页面的性能开始出现恶化。 从用户方的反馈,也证明了这点。此时此刻,有必要迅速排期,敏捷开发,对这些页面进行调优。

 

 

 

其他

 

最新文章
昆仑山
首页 此部分内容前置为铸剑山庄开启紫金熔炉,未开启则不会刷出尸体昆仑山(9,14):尸体,第一次探查,获得【冰穿子】x1;第二次探查获得纸条,阅读得知冰面下面有东西,之后可以掩埋尸体昆仑山(18,16):冰面,使用冰穿子挖凿,选择冰窟窿,
雅思教学培养方案怎么写(雅思培训课程是怎么设置的)
1、第三个方法,社交学习法。每个人都会有疲倦期,这个时候,我们需要内外刺激,而社交学习法就属于外部刺激。也就对应了一句话“一个人可以走得很快,但是一群人才能走得很远。2、雅思如何自学方法如下:听力:雅思词汇是雅思正常考试的核
百度快速排名优化工具(百度seo快速排名优化)
在当今竞争激烈的网络环境中,网站的排名对于企业和个人的在线存在至关重要,百度作为国内最大的搜索引擎之一,其搜索结果页面的排名直接影响着网站的流量和曝光度,为了在百度上获得更好的排名,许多网站所有者和 SEO 从业者开始寻求百度
开发销售打卡“神器”获刑
2023年8月,刚大学毕业的小张到宁波找工作,面试几家公司后发现多数公司都需要通过App来考勤打卡,他觉得特别麻烦,在和同学聚餐时聊起此事,同学向他推荐了一个可以实现虚拟定位打卡的网站。小张登录了这个网站,加了网站管理员的微信。在
使用宝塔搭建环境,以及把自己本地的Web项目通过宝塔发布到远程云服务器上
使用宝塔搭建服务器的环境 什么是搭建服务器环境 所谓的搭建环境其实也就是下载应用,然后把应用对应的端口号在三个地方开启,这三个地方分别是,宝塔的安全菜单的防火墙,阿里云的安全组,阿里云云服务器中
非常聪明的AI眼镜即将到来!VRETF(159786)今日微跌0.67%,利亚德涨19.94%
AI眼镜方向传来新消息。据领益智造消息,12月13日,在AndroidXR发布会上,谷歌与国内消费级AR眼镜厂商XREAL达成了战略合作,共同打造AndroidXR生态。。2024年12月13日,A股市场震荡调整。VR指数成份股中,利亚德涨19.94%,奥飞娱乐涨10.03%
重庆网站建设seo公司 重庆SEO网站建设公司优化指南
重庆网站建设SEO公司:打造企业网络新生态的领航者在当今数字化时代,互联网已成为企业展示形象、拓展市场、提升品牌影响力的核心平台而对于地处西南经济重镇的重庆企业而言,拥有一个高效、美观且具备强大SEO(搜索引擎优化)能力的网站,
文章提取关键词_jieba(IF-IDF/TextRank)
对每个句子进行分词和词性标注处理过滤掉除指定词性外的其他单词,过滤掉出现在停用词表的单词,过滤掉长度小于2的单词将剩下的单词中循环选择一个单词,将其与其后面4个单词分别组合成4条边。
李开复2024年的关键词是AI2.0
来源:@中国企业家杂志微博
百度的关键词排名是多少?如何提升网站排名,让您的业务脱颖而出
百度非常注重网站内容的质量和相关性。如果网站提供的内容对用户有价值,能够满足用户的需求,百度就会优先考虑将其排名提升。因此,确保网站内容丰富、原创且与关键词密切相关,是提升排名的关键。关键词的选择和合理布局至关重要。在网页
相关文章
推荐文章
发表评论
0评