高并发高性能系统设计实践提供八达娱乐,注册至尊娱乐产品设计,加工贸易等业务欢迎广大客商前来洽谈业务合作。
注册至尊娱乐

高并发高性能系统设计实践

来源:八达娱乐 | 时间:2018-10-06

  随着近些年互联网的发展,高并发高性能技术已经非常成熟。移动互联网、电商等聚集了大量的人气,业务的发展,并发用户的猛增,也将原本简单的应用推动到了必须解决性能的问题上,伴随着技术一步一步的升级,系统已不再是每逢促销就宕机,而是轻松应对每次高并发。得益于分而治之、扩容、降级、熔断等一系列方法的应用。

  我曾有幸经历了电商系统业务从几十亿到几百亿规模的过程,系统从单体应用过度到服务化,应用经过了各种拆分、服务化、治理。单个服务达到每日几十亿次调用。

  在我进入互联网领域之前,一直想知道互联网的那些高并发是不是使用了更高级更贵的软硬件,比如Oracle RAC、Weblogic、小型机等。后来才发现这完全相反,大部分使用得更多的是免费、开源、轻量级的软件,比如Mysql、Tomcat、Nginx、Redis、zookeeper、CentOS等等,服务器虚拟Docker化,架构设计上更多考虑水平扩展性,10台服务器支撑不住,是否能支持部署100台、1000台或者更多服务器扩容,只要能通过增加服务器解决的都不是问题。这些都体现在深挖更底层技术特性,将最简单技术用到极致。

  高并发高性能系统是逐步演变、逐步迭代优化而来的,不是一开始就设计出来的,但是系统各个阶段的设计水平影响到后期迭代、重构、优化的难度及速度。本文将会大致介绍一个成熟的高并发系统经历过的阶段及各个环节的高并发的实际技术架构及解决方案。

  可用性是最基本保障,比如要达到99.999%的可用,1年不能超过5分钟宕机,这一点还是比较难达到的,宕机一次,全年KPI就被扣没了,这也是用来衡量系统的可用性的关键指标;

  容灾性比较容易忽略,应用容灾、数据容灾、网络设备基础设施容灾、IDC机房容灾,这要考虑如何能从灾难中快速恢复,满足RTO、RPO的指标,这也是可用性的一重要项;

  安全性就更重要了,一般公司都有技术安全部门把关,但应用开发人员同样需要具备安全的基本知识,可能安全问题出现在某一个对外接口权限控制上,这些还是需要对涉及安全相关的模块重点Code Review及安全渗透测试;

  伸缩性、扩展性,在系统刚开始建立的时候,业务量一般都不大,不需要设计得那么高并发,但是需要有所准备,在系统规划的时候就要考虑到,比如将来业务量增长了之后,我们只需要改造某一个或几个模块就能达到扩展性,或者增加硬件资源纵向或横向增加伸缩性;

  高并发,在系统设计阶段需要考虑,比如一开始设计的时候就考虑未来业务增长几十上百倍,将来系统一定会拆分,那么设计的时候在应用代码内部模块化做好,模块之间松耦合,未来并发量高或需要更多团队维护的时候,就很轻松拆应用。当然我们不要过度设计,把一个简单的系统设计得很复杂,每天访问量都不过万,就要达到亿级流量的容量能力,这样只会让维护性变差。

  一般项目初期开发人数在十几个左右,这个时候通常都是建立一套应用,所有的业务模块都放在一起,核心开发人员也需要对整个系统业务及代码比较了解。好的架构在这个时候就需要设计出模块化,系统内部代码相互尽量保持独立,从控制层到service,到dao层。可以将各模块分配到各开发人员维护,并定期交换模块开发。这样的单系统好处维护方便,包括开发、打包测试、上线等。这样的单系统也可以按照Web控制层、Service服务层简单分应用,这是目前中小项目用的比较多的方式;当项目规模到50人以上的时候,维护性及效率将会降低。

  上图是电商系统的基础模块。当业务量上升,需求大量增加,这个时候技术团队人员也会随着大量增加,因为系统变复杂了,需要更多人参与开发,同时还要处理线上问题等。当人员从原来的十几个开发,增加到近百人的时候,系统需要快速进行拆分,每个小Team负责一个模块。这时候如果系统前期设计及保持得比较好,拆分是很容易的一件事。比如用户中心的模块,用户表属于基础表,大部分模块都会使用到,如果各模块需要使用用户信息,都是从独立模块service接口获取信息,那拆分会很简单,如果所有查询地方都自己去Join这些表,拆分将会是很漫长的过程,且伴随各个Team的协调、配合、沟通才能完成这件事。所以通常建议Join表控制在3-5张表以内,超过的话需要考虑是否未做好模块化了。

  上图是电商系统经过长期的发展逐步形成的模块,这时期系统变得非常复杂,当然开发人员也是比较多,可能一个大部门就只负责其中几个模块。这时期的系统处于高度模块化、服务化,当需要实现一个新的业务模式的时候,比如增加一个拼团网站或App或频道页,只需要各个Team配合,相关的功能拼凑即可完成(当然也需要一些定制开发),不再需要独立设计库存、订单等模块,更多的精力放在前台页面相关业务功能实现上,高度复用及固定团队做熟悉的事情,这样大大增加了系统可用性、安全性等。

  上图中大致分为前台(用户直接操作的相关功能)、中台(后端服务层)、后台(运营或商家使用的相关功能),中台是整个系统中抽离出来的共享服务层,各个业务模块系统基本都会使用到。

  前面聊到的系统发展到成熟阶段,这时候前台用户流量很高,各个子系统并发量都很大,这里解决高并发的最常规手段就是分而治之,每个子系统需要设计考虑容量、TPS。

  如上面图中的价格子系统。“价格业务后台”将各种类型的价格写入数据库,在该系统中业务较为复杂,比如基准价、促销价、团购价、闪购价、拼团价、会员阶梯价等等,这些价格都是由运营人员设置操作的,因此并发量很小,在该系统实现复杂的业务逻辑校验不是什么问题,最后将校验后的价格写入专用的数据库,核心的表一般就在5-10张左右。

  “Price Service”的内部业务逻辑较为简单,只做一些与前台调用相关的逻辑,前台不同的业务类型、平台、渠道等调用该服务,可以获取到相应的价格,该服务基本上对DB是只读操作,如果流量过大,可以扩展更多的备库,流量再大一些就拆库,对该服务来说,做到百亿级别的日调用量不是什么难事,只要堆机器就好(当然系统结构上还要考虑缓存、DB、网络等)。通常按照每天12小时计算出每秒需要的支撑并发量,再乘以3-5倍作为峰值的并发量。这里单台Tomcat服务器能达到的TPS越高,所需要的机器数量就会少很多。系统的性能优化是持续不断的过程。

  上图是前台的相关设计,前台是直接与页面用户能操作的相关功能,通常也是细分了模块,比如商品详情页功能可以是独立的一个子系统,页面加载的内容细分很多次请求,对于后端业务服务层来说,相关数据调用了其他service提供的接口。

  要高并发,必须对调用的接口有高的要求,通常单次调用需要做到5-10ms,不超过20ms。对于调用的Timout时间也是控制在100ms以内或更低,也就是如果调用接口响应超过一定时间,直接调用失败以页面报错等方式快速处理,通常页面部分功能未加载出来,然后再次刷新就能看到,就是这个原因。当某个非关键路径的应用宕机,不影响整体网站的主流程功能。这里要做到高并发,有时候是需要牺牲一些用户体验的(在能接受的范围)。

  前面提到了子系统的高并发,这些系统都需要读写数据库。通常DB的操作中90%以上都是读的操作,也就是写的操作压力并没有那么大。

  考虑性能的时候,可以读写分离,写的操作在主库(对于特殊的一些时延很敏感的读操作放主库),读的操作在备库,这样减少了主库压力,备库压力大的时候可以再增加几个备库解决。

  当主库压力很大的时候,可以考虑将表按照业务模块划分拆分成几个主库,比如用户库、产品库、订单库等。如果这样拆分还不能满足,则可以拆分表,按照时间维度拆分表,近期数据查询频率更高。对热点数据或近期数据表可以考虑继续拆分,比如订单表,可以按照用户维度拆分到6个库,如果压力再增加,则拆分到12个库,按照1拆2的方式,成倍增加数据库主库,可以很好解决主库扩展,提升并发性能的问题。

  表的拆分,通常会引入更多复杂性和局限性,比如按用户拆分表后,需要按商家维度查询该商家下所有用户的订单就比较麻烦。通常用户自己查看订单的并发量要远远高于商家查询订单的并发量。所以商家查询可以低效率一点、或者再同步一份数据到单个库供商家查询。

  服务拆分后,原本容易控制的事务变成了分布式系统事务。整个系统要保证高并发,需要有一定的容忍度,跨服务的事务通常都是事后补偿机制,如果调用较多的子系统,可以类似DB的机制,先写日志,调用成功后更新日志,然后定时任务检查日志中调用情况,然后再次发起调用进行补偿,直到各个子系统都调用成功或回滚成功,如果1h、3h、6h阶梯调用3次还不能补偿,可能就需要技术人工介入处理(当然这样的数据不多,可能是程序Bug引起)。

  高并发中一般不使用分布式事务、二阶段提交事务等,本地事务一般也不使用表锁、行锁等悲观锁,乐观锁是很不错的选择,如果出现并发抢占资源,则让后来者更新快速失败,如果冲突较多,则需要检查程序逻辑了。

  一次操作调用太多的子系统,还需要将同步调用和异步调用区分开,异步调用不占用时间,将调用是否成功放在后续流程操作中检查,这样也能大大缩短一次调用的处理时间,提高并发性能。

  在考虑可用性上,避免将鸡蛋都放在一个篮子里,对于一些独立的业务,可以采用泳道隔离的方式,如果出现高并发流量导致应用宕机,应该将故障控制在一定的范围内,其他业务不受到影响,比如未事先报备评估,业务人员将某商品以极低的价格在外部推广,这时候就可能出现流量陡增,系统被压垮,如果泳道隔离了,只会影响部分业务。对于业务系统后端调用的基础服务子系统也应该分组,也就是同一个子系统的机器被划分组提供给不同业务线使用。

  一次连续的用户操作路径会有很多的系统支撑,各种业务都混在一起,当大促的时候,流量数倍增加,这时候某些页面可能支撑不了,因此需要整理业务流程,定义关键路径。当出现系统不能支撑的时候,快速降级,断开一些不重要的业务,保障大部分功能正常使用。比如大促时,商品详情页上的收藏数量展示、精准化推荐等用户并不关注。大促有什么商品,价格和促销方式是怎样的,及能下单和支付成功,且能看到订单,这是用户操作及关心的主功能,其他功能降级,基本不影响用户体验。

  在实际中,经常有很多S0(订单单量急速下降,甚至跌到0订单/每分钟)的事故是因为一些未被关注的应用,大促前也未充分评估,流量高的时候,这些应用就宕机,结果影响整体网站访问。

  整个网站子系统非常多,千丝万缕,理清主流程,服务治理还是需要一个过程的,但又必须要做好。

  大促临近的时候,通常是根据性能压测指标增加机器,机器不够用就从一些不重要的系统拆借机器,或者临时租用云服务器,组成混合云模式(流量分发的时候要考虑云机器加入集群中的访问时延);除了增加机器,还有一些化解流量的策略。

  业务场景分步操作,比如抢红包,就将抢的操作分开了,先让用户打开红包,再点击抢的按钮,第一步打开的操作查询红包余额并不准确,当第二步点击的时候才出现准确的结果,红包已抢完或抢中。这样分开的设计对用户体验降低较少,但对系统并发量处理呈指数级下降。

  缓存很重要,CDN的图片分布式缓存可以降低对IDC服务器访问量,以及squid缓存静态页面,memcached、Redis缓存业务数据及热点数据,还有JVM本地缓存等。

  秒杀抢购场景使用排队策略,用户页面轮询排队结果,后端服务可以毫无压力的处理。对于库存有限的抢购,可以只放入一定量的请求,其他请求全部挡回去(这些请求进来也不会抢成功),这样对后端也就没有并发压力了。

  多IDC分流,建立多IDC分布于重点区域或省份,这样可以分流,同时也能提升用户访问速度

  限流的策略通常作为灾备方案,当出现系统不能支撑的时候,拒绝一些服务请求,比如Tomcat设置为600最大线程(需要压测评估该系统能接受的TPS)作为保护,避免宕机。还有一些从网络设备上的限流策略,拒绝一部分访问,避免出现整个系统宕机的严重事故。

  所有性能、并发量指标等等都离不开监控。从域名解析到各IDC机房、网络设备层、负载均衡、应用服务器、JVM、磁盘、服务接口响应耗时、缓存、DB等等,要优化性能,这些监控指标都要能清晰的看到才便于分析优化(当然及时报警快速定位问题是监控最重要的);一次用户访问经过很多过程,需要从前到后逐个排查分析,找到瓶颈并优化。

  网站的高并发性能需要逐步重构优化、不断调整架构设计,各个节点模块的优化也都有大致标准的业界通用做法,限于时间和篇幅,本文仅大致描述了一些实践中的方案。

  作者加入点融前,曾在某知名电商公司工作多年,负责过一些架构设计及团队管理,以上内容是在实际工作中总结的一些经验,仅作为一些设计的参考,有不当之处欢迎指出及交流,感谢您阅读到这里!返回搜狐,查看更多

相关www.fccbet.com

    无相关信息