高并发场景以及应对技巧

Posted 明天过后0122

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高并发场景以及应对技巧相关的知识,希望对你有一定的参考价值。

文章目录


高并发现实生活中的场景

我们总是喜欢从软件开发层面理解高并发,其实高并发是解决大数据量业务的一种思路,源于现实生产生活中的场景。高并发现实生产生活中的场景,包括但不仅限于如下内容:战争、新冠疫情防控、医院看病、完成工作任务、工厂生产、参加庙会、乘坐公共交通等等。如何提高这些现实生产生活中高并发场景的效率、消除弊病,都是我们需要解决的问题。

1 高并发基础

1.1 并发与并行

Erlang 之父 Joe Armstrong 用一张5岁小孩都能看懂的图解释了并发与并行的区别。

并发是两个队列交替使用一台咖啡机,并行是两个队列同时使用两台咖啡机,如果串行,一个队列使用一台咖啡机,那么哪怕前面那个人便秘了去厕所待半天,后面的人也只能等着他回来才能去接咖啡,这效率无疑是最低的。

并行(parallelism):

所谓并行,就是同时执行的意思。判断程序是否处于并行的状态,就看同一时刻是否有超过一个“工作单位”在运行。所以,单线程永远无法达到并行状态。要达到并行状态,最简单的就是利用多线程和多进程。

并发(concurrency):

并发指的是程序的“结构”。当我们说这个程序是并发的,实际上,这句话应当表述成“这个程序采用了支持并发的设计”。好,既然并发指的是人为设计的结构,那么怎样的程序结构才是支持并发的设计?正确的并发设计的标准是:使多个操作可以在重叠的时间段内进行。

1.2 什么是高并发

高并发(High Concurrency)一般是指,通过设计保证系统能够同时并行处理很多请求。评价高并发处理能力的一些指标有响应时间(Response Time)、吞吐量(Throughput)、每秒查询率QPS(Query Per Second)、并发用户数等。

响应时间:系统对请求做出响应的时间。例如系统处理一个HTTP请求需要200ms,这个200ms就是系统的响应时间。

吞吐量:单位时间内处理的请求数量。

QPS:每秒响应请求数。在互联网领域,这个指标和吞吐量区分不太明显。

并发用户数:同时承载正常使用系统功能的用户数量。例如一个即时通讯系统,同时在线量一定程度上代表了系统的并发用户数。

高并发:同时或者在极短时间内,有大量的请求到达服务器,每个请求都需要服务端耗费资源进行处理,并做出相应的反馈。

1.3 从服务端视角看高并发

服务端处理请求需要耗费服务端的资源,比如能同时开启的进程数、能同时运行的线程数、网络连接数、CPU、I/O、内存等等,由于服务端资源是有限的,那么服务端能同时处理的请求也是有限的。

高并发问题的本质就是:资源的有限性。

1.4 高并发带来的问题

高并发问题描述的是客户端请求服务端的问题,并非我们常说的Web浏览器到服务器的请求。高并发问题也不是互联网应用独有的。

客户端同时大量请求服务端,服务端的处理和响应会越来越慢,甚至会丢弃部分请求不予处理,更严重的会导致服务端崩溃。

1.5 高并发问题层面


从“Web请求”层开始,到“Web应用”层,“Web应用”层可以分为“Web前端”和“Web后端”,再到“业务服务”层,最后到“数据库”层。
分层架构下的客户端、服务端解释如下:

  • “Web请求”层与“Web前端”层互为客户端、服务端;
  • “Web前端”层与“Web后端”层互为客户端、服务端;
  • “Web后端”层与“业务服务”层互为客户端、服务端;
  • “业务服务”层与“数据库”层互为客户端、服务端。

2.高并发应对技巧

2.1应对思路

2.1.1 客户端


同为客户端的应对思路有:
尽量减少请求数量,比如:依靠客户端自身的缓存或处理能力,过滤非正常请求;
尽量减少对服务端资源的不必要耗费,比如:重复使用某些资源,如连接池;客户端处理的基本原则就是:能不访问服务端就不要访问。

2.1.2 服务端


同为服务端的应对思路有:
增加资源供给,比如:
(1)更大的网络带宽;
(2)使用更高配置的服务器、高性能的服务器;
(3)使用高性能的数据库服务器。
请求削峰限流,比如:漏斗桶、令牌桶、计数器、消息队列。
请求分流,比如:
(1)使用集群;
(2)分布式的系统架构。
应用优化,比如:
(1)使用更高效的编程语言;
(2)优化处理业务逻辑的算法;
(3)优化访问数据库的SQL。

2.1.3 服务端处理基本原则

服务端处理基本原则是:削峰限流、分而治之,并提高单个请求的处理速度。

2.2 应对手段

后续将按照每个层面来谈谈应对的具体手段,不是高并发应对方案,方案是要结合具体的应用,综合分析,选择合适的手段组合起来的。

同时,以下提到的每个层面的应对手段都是“包含但不限于”。

2.2.1 客户端

  • 尽量利用浏览器的缓存功能,减少访问服务端,比如:js、css、图片等;
  • 可以考虑利用压缩传输的功能,减少网络流量,也会提高传输速度;
  • 考虑使用异步请求,分批获取数据。

2.2.2 服务端(CDN、nginx

  • 使用CDN服务;
  • 动静分离,部分静态资源可以直接从Nginx返回;
  • 按请求的不同,分发到不同的后端进行处理,比如:负载均衡、业务拆分访问等;
  • 前面再加上一层来做多个Nginx的负载均衡,比如:LVS、F5、Keepalived等;
  • 对动态内容进行缓存,尽量减少访问后端服务(或采用其他中间件)。

2.2.3 服务端(Web Server)

  • 使用最新的JVM,并进行配置优化,Java优化;
  • 动态内容静态化;
  • 对Web后台服务器进行配置优化,比如:调整内存数量、线程数量等;
  • 对Web后台服务器进行集群,或者提供多个能提供相同服务的Web服务器,以实现负载均衡;
  • 仔细规划Web后台服务器上部署的应用规模;
  • 提供专门的图片、文件、视频等静态资源服务器。

2.2.4 服务端(业务服务)

  • 使用最新的JVM,并进行配置优化、Java优化;
  • 动态内容静态化;
  • 优化处理业务逻辑的算法;
  • 合理高效的利用缓存;
  • 优化访问数据库的Sql,可以考虑利用存储过程等数据库的能力;
  • 合理使用多线程,加快业务处理;
  • 部分业务可以考虑内存数据库,或者进行纯内存处理;
  • 尽量避免远程调用、大量I/O等耗时的操作;
  • 合理规划事务等较为耗资源的操作;
  • 合理使用异步处理;
  • 对部分业务考虑采用预处理或者预计算的方式,减少实时计算量;
  • 内部系统间的业务尽量直接调用、直接处理,减少WebService、工作流等;
  • 对业务服务器进行集群,或者提供多个能提供相同服务的业务服务器,同样借助Nginx以实现负载均衡。

2.2.5 服务端(数据库)

  • 合理选择数据库的引擎,比如mysql的InnoDB与MyISAM引擎;
  • 进行性能配置优化;
  • 可以考虑使用存储过程来处理复杂的数据逻辑;
  • 数据库集群,进行读写分离;
  • 合理设计数据库的表结构、索引等;
  • 分库、分表,降低单库、单表的数据量;
  • 合理使用NoSql。

3. 高并发场景

以下篇幅通过分析秒杀业务场景为例,针对性地采用上面提到的一些知识,提供秒杀业务场景的应对方案,当然同样是包括并不仅限于这些内容。

3. 1 秒杀

秒杀场景一般会在电商网站举行一些活动或者节假日在12306网站上抢票时遇到。对于电商网站中一些稀缺或者特价商品,电商网站一般会在约定时间点对其进行限量销售,因为这些商品的特殊性,会吸引大量用户前来抢购,并且会在约定的时间点同时在秒杀页面进行抢购。

秒杀特点:

  • 秒杀时大量用户会在同一时间同时进行抢购,网站瞬时访问流量激增;
  • 秒杀一般是访问请求数量远远大于库存数量,只有少部分用户能够秒杀成功;
  • 秒杀业务流程比较简单,一般就是下订单减库存。

3. 2 秒杀设计理念与思路

限流: 鉴于只有少部分用户能够秒杀成功,所以要限制大部分流量,只允许少部分流量进入服务后端。

分流:负载就是问题,高并发问题。均衡就是解决手段。

削峰:对于秒杀系统瞬时会有大量用户涌入,所以在抢购一开始会有很高的瞬间峰值。高峰值流量是压垮系统很重要的原因,所以如何把瞬间的高流量变成一段时间平稳的流量也是设计秒杀系统很重要的思路。实现削峰的常用的方法有利用缓存和消息中间件等技术。(nginx的漏斗原理)

异步处理:秒杀系统是一个高并发系统,采用异步处理模式可以极大地提高系统并发量,其实异步处理就是削峰的一种实现方式。(可以把数据放入表里面,后台排队处理)

内存缓存:秒杀系统最大的瓶颈一般都是数据库读写,由于数据库读写属于磁盘IO,性能很低,如果能够把部分数据或业务逻辑转移到内存缓存,效率会有极大提升。

可拓展:当然如果我们想支持更多用户、更大的并发,最好将系统设计成弹性可拓展,如果流量来了,拓展机器就行。像淘宝、京东等,双十一活动时会增加大量机器应对交易高峰。(上云容器化,高度可扩展性)

3. 3 秒杀应对方案

  • 准备工作:
    – 系统最好独立部署;
    – 做好系统性能容量规划(一般7折计算),系统优化,容灾过载保护;
    – 做好系统拆分,比如:按功能模块、按实时/非实时、按动态/静态等等;
    – 设置定时上架的时间;
    – 服务器时钟同步;
    – 动态生成下单页面的URL。

  • Web应用层:
    – F5/LVS + Nginx来接收高并发的请求,并做负载均衡;
    – Nginx + Lua + Redis 来做请求队列,并实现一些基本控制,比如:限流、账号参加次数检查、同一IP请求数检查等;
    – Nginx、Varnish或者其他中间件来缓存静态页面和静态资源;
    – 进入Tomcat集群,先做一个预处理,就是判断这些账户是否能参与活动,比如:账号等级是否足够、账号行为是否正常、是否在黑名单上等。

  • 业务服务层:
    按照Redis的请求队列进行先后处理;
    纯内存操作 + 异步;
    控制超卖;
    Redis里面存放着SKU的库存数据;
    处理成功的信息也存放在Redis里面。

  • 其他全局考虑:
    合理设计接口;
    应当时告知用户结果;
    考虑业务规则,比如减库存的时机;
    服务器尽量集群,并做HA,避免雪崩;
    库存预热,秒杀前,通过定时任务或者运维人员提前把商品的库存加载到Redis中,让整个流程都在Redis里面;缓存服务器如果要重启,也要做预热;
    对抗作弊,比如:同一账户同时发多个请求、同一IP同时发大量请求、秒杀器采用多账户多IP发送请求等;
    服务单一原则,秒杀就是秒杀服务,商品就是商品服务,一个服务挂了,不至于把其他服务搞崩溃;
    削峰填谷MQ,你可以把它放入消息队列,然后一点点消费去改库存就好,不过单个商品其实一次修改就够了,这里说的是某个点多个商品一起秒杀的场景。

总结

提示:在想想

以上是关于高并发场景以及应对技巧的主要内容,如果未能解决你的问题,请参考以下文章

高并发架构系列:Netty的实现原理特点与优势以及适用场景

运维人员如何应对高并发

运维人员如何应对高并发

分布式架构进阶:如何应对高并发的用户请求

java高并发高频面试题:Sempahore的使用场景与常见误区

阿里面试系列Java线程的应用及挑战