原创 淘系技术 淘系技术 7月12日
在互联网公司,经常面临一个“三高”问题: 高并发、高性能、高可用。
我们经常收到一些同学提问:我没有高并发项目经验,工作中没有这样的场景。但是面试的时候经常被问到高并发、性能调优方面的问题,有什么办法可以学习或者解决吗?
这种时候,你需要有一个全局的技术视野,熟悉一些常用的系统优化方法论,以及学会一些关于系统设计的解答思路。
今天我们邀请了 3 名淘系技术工程师,给大家分享一些他们在高并发项目的学习实践经验&面试回答经验,希望能够对你有帮助。
01
淘系技术部-产品技术-昭明
“高并发系统是可遇不可求的,但其实是可以通过压测来模拟的。”
现实中,哪怕是大公司,高并发系统也是可遇不可求的。不过,高并发其实是可以通过压测来模拟的。
高并发的背后,核心是高可用和低延迟。所以我们其实是想有能力设计一个系统,在高并发访问的时候,系统依然可用,而且响应速度不会变慢。
想提升高并发系统的设计和开发能力,有2个方面:
- 系统的学习相关理论;
- 找一个目标系统,不断想办法去提升他的性能。
前者是后者的理论基础。
如果想从事一个高并发系统开发的岗位,要学习的相关技术其实是很多的,这些技术核心就是解决高并发情况下如何保持系统的高可用和低延迟。
以Java工程师为例,互联网程序员面试中经常会考察的内容包括:
架构设计
高可用与稳定性、事务一致性、多副本一致性、CAP理论。
相关技术
多线程(JUC/AQS/线程池)、RPC调用及框架(如Thrift)、NIO及NIO框架(如Netty)、高并发框架(如Disruptor) 、微服务框架(SpringBoot)、微服务治理(Spring Cloud)、数据库相关技术(如:索引优化、分库分表、读写分离)、分布式缓存(如redis)、消息中间件系统(如RabbitMQ)、容器技术(如docker)。
工具
系统性能查看(top、uptime、vmstat、iostat)、压测工具(如ab、locust、Jmeter、go)、线程分析(如jps、jstack)等。
当然,一开始,我们不可能逐一把这些技能全部掌握,我们可以从一个实际项目入手,不断的把这些技术用上去,发现哪些知识不足,再去补充相关的知识。
“如何设计一个好的秒杀系统“,一定是互联网大厂面试中最常问的一个问题。所以从设计一个秒杀系统开始实践,是个不错的选择。
秒杀系统的特点:
- 瞬时并发量大
秒杀时会有大量用户在同一时间进行抢购,瞬时并发访问量突增 10 倍,甚至 100 倍以上都有。
- 库存量少
一般秒杀活动商品量很少,这就导致了只有极少量用户能成功购买到。
- 业务简单
流程比较简单,一般都是下订单、扣库存、支付订单。
设计秒杀系统的关键点
- 限流
由于活动库存量一般都是很少,对应的只有少部分用户才能秒杀成功。所以我们需要限制大部分用户流量,只准少量用户流量进入后端服务器。
- 削峰
秒杀开始的那一瞬间,会有大量用户冲击进来,所以在开始时候会有一个瞬间流量峰值。如何把瞬间的流量峰值变得更平缓,是能否成功设计好秒杀系统的关键因素。实现流量削峰填谷,一般的采用缓存和 MQ 中间件来解决。
- 异步
秒杀其实可以当做高并发系统来处理,在这个时候,可以考虑从业务上做兼容,将同步的业务,设计成异步处理的任务,提高网站的整体可用性。
- 缓存
秒杀系统的瓶颈主要体现在下订单、扣减库存流程中。在这些流程中主要用到 OLTP 的数据库,类似 MySQL、Oracle。由于数据库底层采用 B+ 树的储存结构,对应我们随机写入与读取的效率,相对较低。如果我们把部分业务逻辑迁移到内存的缓存或者 Redis 中,会极大的提高并发效率。
从0到1搭建一个秒杀系统,也并不容易,涉及到很多前端、后端、中间件的技术。这个跟其实是所有公司的工作常态,大部分时间也是在搭架子,真正做技术优化的时间并不多,经常是在业务量突增或者大促活动来临时,集中搞一波性能优化。
所以,如果没有实际的高并发项目可做,自己弄个秒杀系统自娱自乐也是不错的。
搭建系统 -> 压测 -> 发现问题 -> 学习知识 -> 优化系统,通过这样的循环,相信你一定既能体验到学习的乐趣,同时实力也大幅提升。
02
淘系技术部-行业与智能运营架构组-仲春
“在面试时被问到高并发经验时不要慌,按照以下过程表达即可体现你的高并发设计能力:优化单请求耗时、提高单机并发能力、提高整体并发能力。”
个人认为,其实我们并不用去追求严格意义上的高并发经验,因为很多时候都没有这样的机会给到你,对于高并发的处理经验主要体现在日常的积累以及对自己的严格要求上。
为什么总在说高并发?
在并发不高的场景下,不区分经验是否丰富的任何人都能完成基本的业务开发,而且不会产生任何性能问题,下游依赖、底层存储依赖都不会对你的系统产生影响,但是在并发很高的时候,一切都变了,可能由于高并发环境时下游抖了几ms、db由于高写入或者备库读压力过大而导致主备延迟了一下,你的系统或者业务都会产生故障。
如何积攒“经验”?
对于这个问题,我总结3点可落地:
- 系统的设计优化
首先系统只有无状态的,才能不断横向扩展,才能支撑流量的变化,在业务层的高并发大多都需要不断扩容来支持,但是扩容也不是最根本的方式,如果系统不做优化,一开始扩容大概率是有效的,到一定阶段后就会发现情况开始恶化,因为底层的依赖竞争开始激烈,失败开始增多。优化的尽头往往是对下游依赖和底层数据层的优化,解决方案大多是常见的缓存分层、读写分离、分库分表、异步化等等,但是引入这些技术方案时,会带来一些副作用,接下来你需要解决和屏蔽这些副作用。
- 业务逻辑的优化
当你只是在负责一个流量不大的系统时,是否就没有高并发的机会了呢?其实不然,你需要不断严格要求自己,让业务跑的更快,例如:将单次请求响应耗时从100ms优化到20ms;单机能力从100qps提高到500qps,同时cpu消耗上涨不明显;优化单次请求对缓存和db的放大系数降低,减少对缓存和db的压力。在这个过程中你将积累大量的实战经验,完成业务开发很简单,但是完成一个高效且具备高扩展性的业务开发却是很难的,往前多想几步,你会收获很多。
- 压测验证
在业务体量没有高并发的情况下,只有自己人为创造流量来验证(不过前提是你的系统支持全链路压测,否则压测数据会污染线上真实环境,如果暂时不支持,那么恭喜你,你有机会做一次全链路压测改造了),通过验证在目标水位下的系统表现、机器表现,再继续重复前面两个过程,不断迭代,直到无法扣细节,提高性能;
如何展示自己的高并发经验?
只要在日常研发过程中严以律己,做好各项设计和优化,不随意写难易扩展和难易维护的代码,面试的时候就能聊下去。在面试时被问到高并发经验时不要慌,只要按照以下过程表达即可体现你的高并发设计能力:
- 如何优化单请求耗时
这里你会阐述如何设计和改造系统架构,有可能涉及到jvm的参数优化、各种依赖是如何选型,过程中你积累了哪些选型和优化的方式;
- 如何提高单机并发能力
这里你会阐述在你的业务中,单机并发能力受限于哪些关键点,这里主要的挑战点是单机的限制条件以及单机资源的竞争,你是如何设计克服的,过程中你积累了哪些设计原则;
- 如何提高整体并发能力
这里你会阐述在集群环境下最重要的亮点,就是如何处理跨机器的资源竞争以及数据的一致性问题,这里将体现你整体业务架构设计能力;
综上所述,面试时并不是要求你一定要有真实高并发的项目经验,项目经验只是为了验证你真的做过一些设计和优化,如果你能将高并发场景下的设计原则和可能遇到的问题场景和解法都表达清楚,那么我相信面试官也是认可的。
03
淘系技术部-淘系基础架构-罗集
“对于高并发系统设计,个人推荐可以自底向上的分成三个部分,首先是建立基础知识体系,其次是熟悉业界解决方案,最后是分布式系统设计。”
首先高并发的系统也不是最初就设计出来的,一切解决方案都是来自于业务场景。
大多是针对特定时期内的问题与挑战,一步一步演化出来的。即便是在有高并发场景的公司里的研发同学,如果不是去参与解决这些问题,往往也不能直接获得高并发的经验积累。所以没有场景的公司里面的研发同学,大家的起点其实是差不多的,完全不用虚,关键还是在于掌握其中的核心科技。
对于高并发系统设计,个人推荐可以自底向上的分成三个部分,首先是建立基础知识体系,其次是熟悉业界解决方案,最后是分布式系统设计。
知识体系的建立要更多的去关注底层,如算法、缓存、多线程、并发、JVM、OS、网络、分布式理论等,这些东西相对稳定,在这些底层技术的基础上的解决方案好像层出不穷,如各种缓存技术、各种消息队列、各种数据库。但是掌握了底层原理,再去看上层的解决方案就能有触类旁通的效果。对于最后的分布式系统设计,就是针对具体业务场景去应用相应的技术,组装成一套体系的方案。
对于知识的学习资料网上已经非常多,可以自行学习建立体系。自己公司没有具体的场景,就去各大公司的技术博客学习业界方案。业界方案的学习推荐更多的思考其中的原因(Why),这个才是系统设计的核心。
比如一个环节拿掉会对系统产生什么样的影响?换成另外一个技术会有什么不同?下面主要讲一下面试中对于系统设计的解答思路。
第一步,提取设计目标
分布式系统设计中一定要明确自己的设计目标,比如系统的延迟和吞吐量,有时候是不可兼得的,会直接影响到具体的技术选型。面试中自己没有实际的项目不要紧,可以针对某个假设的业务场景提取出系统设计的假设,多与面试官沟通交流,说明清楚自己是基于怎样的需求来做这个设计。
第二步,核心模块设计
接下来就是对系统的建模,需要哪几个核心模块,这个阶段主要关注功能的满足,比如核心的算法选择,数据模型设计。
第三步,扩展设计
识别系统的瓶颈点,结合所需要达到的系统指标。合理的对系统分层,并选用常见的扩展技术,如:
- 负载均衡
- 水平扩展
- 缓存
- 数据分片
最后,高并发系统的设计是一个负责且系统的工程,目标绝不仅仅只关注性能,实际上要同时关注高可用和扩展性。所以在实际方案的设计中,除了要考虑正常情况下性能指标是否能够达成,还要考虑在各种异常情况下系统是否能处于可控的状态,如不能因为一个异常情况就发生系统雪崩,另外互联网业务都是处于高速迭代和发展的过程,要保证未来的场景有足够的演进空间。
如上,我们在日常工作和面试经历中并不一定能够真实经历高并发系统,但是我们依然有多种学习和实践方式获得类似经验。如果能够尝试去学习和理解高并发场景下的设计原则,以及可能遇到的问题场景和解法,等真正遇到高并发项目的时候,效果也是事半功倍。
希望以上分享对大家有所帮助。一起加油~