网站高并发解决方案-理论知识


本文转自:http://www.php20.cn/article/sw/%E9%AB%98%E5%B9%B6%E5%8F%91/244

1. CDN代理层

在高并发下,为了解决带宽问题,全站必须做前后端分离操作,所有前端资源都可进行CDN代理,进行缓存静态资源,分散服务器带宽压力。

同时,app端,小程序端等本地资源无需担心这个问题。

2. 防火墙层

1、在大多数并发情况下,都可能存在恶意请求,例如CC,DDOS攻击,通过脚本,1秒请求100次,1000次请求,我们可直接认定该请求以及请求后的客户端为恶意请求,拒绝该客户端请求。

2、由于数据网络的特殊性,可能存在多个手机网络共用一个ip的情况,理论上不能直接封停ip,而是需要根据该次请求客户端附带的其他信息(ua标识)来用于拒绝。

3、同时,对已登录用户做好限流,同一个用户,理论上一次性不可能超过10次接口请求(静态资源不算)

4、防火墙其他规则可执行研究

3. 网关层

网关层可以和防火墙层可以为同一个逻辑,通过防火墙后,进行请求调度,例如 Nginx 负载均衡。网关层需要对请求进行调度,将请求通过轮询/空闲判定,权重判定等方式,把请求分配到多台服务器,进行服务器压力分担。

==注意:所有内部通信,最好都为内网环境,降低带宽压力,以及提升相应==

4. 微服务层

微服务层是个概念性层,可要可不要,在微服务层,可对请求进行服务分散,在大压力情况下,有必要关闭一些微服务应用进行服务降级,保证主要服务的运行。

例如:在淘宝双十一时,关闭了退款通道。

例如:当商城高并发时,关闭查看历史订单功能,关闭小游戏功能,等等。

微服务层可能会出现分布式事务问题,有一定的难度。

5.进程模型优化

在传统 php-fpm 模型中,单进程作为同步阻塞模型,一个进程在同一时间只能处理一个请求,当出现io阻塞后,进程会一直被请求占用,直到io结束,如果需要提升并发,就必须增加进程数,增加进程数意味着cpu调度进程压力增大,导致cpu耗费资源加大。

通过 swoole 的多进程多协程并发模型,一个进程可同时处理多个请求,cpu只要调度少量的进程,即可实现处理更多的请求。

6. PHP解释层优化

在正常php-fpm中,php运行需要经过以下几个步骤:加载php文件->逐行解释->运行 一个php项目,一次请求可能存在10-50个文件(laravel框架更多),每次请求进来,都需要重新引入文件,加载文件,导致磁盘io负载暴涨。

==我们可以通过opcache对文件进行解释加载进内存,二次请求不会再去重新加载php文件如果不想做opcache,也可直接将项目代码放进内存文件系统中,也可通过swoole、wokerman等常驻内存框架提升一点速度,也可实现一次加载永久存在的目的,提升性能。php作为服务端语言,主要瓶颈在于io,在高并发下,这些优化也是有限的。没有过于追求的必要。==

7. 服务器缓存层

理论上,一次接口请求进来,非即时性查询,高频请求,都必须先经过缓存层,通过缓存减小数据库压力。

例如:商品缓存,文章缓存等等。

==注意:为了避免缓存穿透,需要对所有缓存定时更新期限,并且将失效时间进行错开,确保不会出现一瞬间所有缓存失效,导致请求全部进入数据库。为了避免内存溢出,,需要对所有缓存字段进行管理,做失效时间,定时删除垃圾数据。==

8. 并发锁相关

在并发下,如果对数据准确度有一定要求的话,将涉及到并发锁功能。

在MySQL中,MyISAM引擎虽然插入、查询性能高,但是它使用表锁,如果在大表更新情况下,将造成锁表,导致全服务器请求都将锁住等待,所以MyISAM不能用于大表更新等业务,只适合做日志记录。

同时,InnoDB支持事务,行级锁,在更新用户金额时,可使用InnoDB存储引擎的表存储用户金额,进行行级更新。

可查看:并发锁

==注意:InnoDB虽然作为行级锁,但是也需要考虑操作表的单位数量,例如用户金额,理论上只有用户自身请求,并发量并不大,就算是锁表,也不会影响到其他用户的操作。(如果你非得用脚本点1000下下单,那也是你牛逼,给你锁表1000秒也是你自找的)。但如果是商品库存,将不能直接使用 InnoDB 实现行锁,原因是该数据可能会被成千上万的用户进行请求,当锁住后,其他请求都需要等待,极度影响用户体验。==

9. 异步队列压力

如果是高并发场景为瞬时并发,例如商品秒杀只有1秒,其他时间都为低流量请求情况,可通过队列转为异步处理,前端等待n秒获取异步结果
通过异步队列,可分散瞬时并发带来的压力,使得服务器不会瞬间宕机导致出错.

==注:异步队列处理缺点在于用户不能即时获取到结果,但是一般不会太久,如果超出3秒,可直接丢弃该请求,直接给用户返回失败.==

==如果是不需要获取结果的,例如插入日志,发送邮件,可直接使用队列==

10. 数据库主从

为了避免数据库压力过大,可对数据库做主从环境,非主要数据全部从从数据库读取,减少主数据库压力.

可查看: 关于mysql集群主从服务器搭建

==注意:需要注意主从同步数据延迟问题,以及主从断开后数据恢复问题==

11. 数据库分表

可查看:mysql分表详解

通过对数据库进行分表,降低单表锁表情况,分散单表查询压力.

12. 数据库索引优化

通过优化数据库索引,保障查询时命中索引,减少 临时表

可查看: Mysql索引优化

13. 尽量不要出现报错

虽然 notice 报错不会影响服务正常运行,但是一次报错,涉及到了php底层的错误拦截机制,会影响非常多的性能,所以尽量不要出现任何报错.

解决任何可能存在的代码报错情况,改用自己的方式拦截,记录日志.


文章作者: Virus
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Virus !
 上一篇
vue分页组件 vue分页组件
这里的分页样式和bootstrap有关,样式可以自己改,这个无所谓 pagination组件<template> <div class="pagination" role="group" aria-label="分页
2020-07-01
下一篇 
数组模拟栈 数组模拟栈
使用数组进行模拟栈的实现 数组初始容量为10进行测试 使用一维数组进行存储元素 选择Object类型,能够存储Java中的任何引用类型的数据 StackMoc.java /** * @ClassName: StackMoc *
  目录