高迸发解决方案2

63 篇文章 0 订阅
14 篇文章 0 订阅

因各种各样的原因,我们遇到了一些需要高迸发支持的场景。

场景业务需求:
1、高迸发
2、有大量读写操作,且需要即时响应
3、稳定的性能

第一步:增强服务能力 - SLB 负载均衡器

用户C端是通过后端程序去操作数据的,如果在某个时刻用户流量大到了一定程度后,那么我们单台服务器很难支撑住如此大的流量。导致服务器宕机。而导致服务器宕机的原因有很多,我们来具体分析一下
1、因流量过大,致使服务器的带宽占满,导致用户下载速度慢,体验差
流量是相互的,用户在上传内容的时候,就是服务器在下载的时候,服务器在响应数据给用户的时候就是用户在下载的时候,当用户群体庞大到一定程度,流量就被占满,导致所有人的下载速度都受到了限制,从而也会引发一系列的问题
连接超时:因数据没有在一定时间内完整传输给用户。
请求等待:带宽占满了,需要等待服务器下载完成后处理。
CPU性能跑满:用户一边在请求,一边服务器在响应,但服务器的吞吐因流量变小,导致大量的tcp请求进入等待状态,而服务器需要维护这个等待状态(http 3次握手),维护状态需要消耗cpu
404响应:网站已被宕机,原因:流量过大 -> 连接超时 -> 请求等待 -> cpu性能跑满 -> 404响应
增大服务器带宽流量

2、机器计算力不够
业务逻辑太复杂、单个接口消耗的资源较大(如上传图片、音频等)。在不考虑带宽的情况下,处理图片和音频计算机也需要在请求中维护的(需要现在内存中接受来自用户C端的上传,然后保存在本地,等待请求结束后才释放资源)
增加服务器配置

3、已达到单台服务器的上线,还是无法支撑用户群体的访问
那就多台服务器为用户C端群体服务,如负载均衡。具体实现原理去翻翻我其它的章节

4、SLB
实时监控机器性能节点,当机器性能达到某个阀值后,就会被认为性能即将耗尽,此时SLB将自动创建一个新的服务器实例(即是新的服务器)并挂载到自己的监控下来为用户提供服务。

第二步:增加数据库能力 - 读写分离、数据分片、双机热备、连接池

一般导致网站崩溃的地方就是数据库,而数据库的重要性不用多说,首先我们可以去使用第三方云产品(RSD 或是 poloarDB )一般都是默认使用和实现了双机热备的,这个不用我们多说。
1、连接池
传统和数据库访问都是用的时候就连接数据库,用完之后就立即释放(php)。这样会带来和数据库交互时建立连接的开销。平时低频访问没啥子,但如果是高迸发下,这个就不友好了,最好是做一个数据库连接池来降低程序与数据库之间建立连接时的开销。(即首次使用后不会释放这个连接,而是加入到连接池中,当下次再用数据库时,就不必重新建立连接,从连接池中直接拿来用)。如阿里云RDS 或是 polarDB 就为我们实现了这个连接池,如果你是php,可以像平时访问数据库一样访问使用,他本身就是一个数据库中间件。即是我们由访问数据库变成了访问数据库连接池中间件

2、读写分离
绝大部分的高迸发场景都是大量的读,如果是这样的话就有两种方案
方案1:redis 集群 或是 分片
如果你的业务是对单个数据进行大量的访问,那么我建议你将数据查询出来后,将这个数据分发给多个redis(redis最好在不同的物理机上,避免CPU资源占用冲突),然后在查询的时候随机从这多个redis中获取数据,目的是降低单台redis的压力,不过一般一台redis就够用了。

如果你的业务对多个数据进行大量的访问,且每个数据访问的频率都差不多,那么就做分片,将数据A分给redisA、数据B分给redisB、在查的时候,要什么数据就去哪个redis中获取。

方案2:mysql 集群 或是分片
如果你的业务是对单个数据进行大量的访问,那么首先要考虑到mysql连接数(mysql的配置)是否支持这么多的流量访问。是否可以做一个连接池来做连接数缓冲。其次考虑我的表索引优化怎么样,给用户获取时,单个请求消耗的性能如何,测试大迸发下数据库消耗又如何。
1、集群:采用读写分离模式,读库从主库上获取binlog二进制文件,从而达到主从数据同步的功能,而用户C端大量的请求将从读库上获取数据,如果我们创建多个读库,那么就有多台读数据库来为用户提供服务,从而降低了单台数据库服务器的压力

2、分片:将数据归类,分别放在不同的数据库中,常见的如业务拆分后挂载在不同的服务器上而数据库也随着迁移到了不同的服务器上。此时访问数据就是从不同的数据库中获取不同的数据

如果你的场景还要求你的服务能够及时响应怎么办呢?
常见的如秒杀活动,要求你立即给一个反馈结果。(每秒处理20W请求,不考虑服务器,只考虑数据库稳定性)
不能使用队列MQ(队列还需要后台慢慢轮询处理,高迸发情况下,这个等待的时候可能会有点长,哪怕多几个处理进程,也不能保证可以立即响应)。
redis也撑不住(迸发量极大情况下,redis单台10W就顶天了,且不支持事务,秒杀是需要事务支持的,不能超库存)
个人见解:采用mysql、但是一台mysql。我们可以将这个秒杀商品的库存分摊给100台mysql数据库,并且mysql数据库均位于不同的物理机上。用户C端在秒杀时,会有一个工作流程如下:
1、检查当前哪些数据还有库存(这一步并不是轮询所有数据库,而是在redis集群中存放的配置,这个配置是 数据库标识符=>是否还有库存 如 db0=>1 db1=>0 代表db0有库存 db1没有了)
2、从有库存的数据库集合中随机抽取一个给用户使用
3、用户获得数据库地址后去这个数据库执行业务程序(秒杀逻辑),因数据库返回无库存异常(没有库存了),触发库存关闭机制(去redis集群中关闭这个数据库的库存)
4、在后台跑一个任务调度(每30s执行一次,工作任务为检查这100台数据库哪些还有库存,哪些没有库存。并保持实时与redis的数据库配置状态同步)

第三步:CDN 网络分发

用户在访问浏览时会下载大量的静态资源,如图片,css,js,音频、视频等,不用犹豫,将这些内容全部丢给CDN去处理,即是用户不再向业务服务器访问下载这些资源,而是向CDN访问下载这些资源,CDN本质是网络分发,好一点的服务商在全国都有自己的节点,且理论上性能是没有上限的,你不用去考虑CDN的性能问题。

性能考虑

  • 数据存取:redis配合mysql,redis承载大量读操作,mysql承载写操作(写操作完成后,如果有需要设计一个触发器,更新redis缓存信息),mysql可做读写分离、分片、集群。redis可做分片和集群
  • 服务器性能:如果采用php-fpm或是swoole异步风格协议,需要考虑最大进程数及CPU的核数,同时还需要考虑接口耗时时间(因一个php-fpm-work进程或是swoole-work进程在同一时间只能处理一个请求,当这个请求比较耗时(如第三方restful接口),就会把进程阻塞住,降低服务器吞吐)。
    如接口比较耗时,可对程序进行优化,如队列消息,协程,延迟助力等。将于用户交互所做的工作内容简化,将一个任务拆分成多个小任务执行。
    如机器性能已达到瓶颈,可搭建分布式服务器系统。
  • 文件下载:很简单,将所有的外部资源全部交给第三方操作,OSS搭配CDN,完美的选择
  • 程序优化:
    程序优化方面主要考虑一个接口运行时关于时间复杂度的问题。
    时间复杂度 = 物理层(带宽、物理机所在地域、DNS解析速度、服务器配置、内核优化) + 程序运行耗时 + I/O阻塞耗时(连接数据库、数据库CURD操作、redis连接、redis操作、http restful接口访问、rpc、文件操作等)
    我们能控制的只有程序运行耗时和I/O阻塞层面,物理层那是公司和运维的事情。
    如果是程序运行耗时,那么我们要考虑如何将工作任务拆分,是否可以使用队列、协程、任务调度等功能来处理这部分工作。
    如果是I/O阻塞耗时,把么我们要考虑具体阻塞的地方是哪里,数据库阻塞(做读写分离、配合redis优化抗压),restful接口阻塞(告知该接口开发者,提升接口处理性能。本地做接口内容缓存),rpc(反馈给该接口的开发人员)

坚信,办法总比困难多。遇到问题不要逃避,迎面而上,在无数的问题中找到解决方案,才是一个优秀开发者的品质。
坚信,当你无法解决某个问题的时候,一定是你某个知识点还没有掌握牢固,发现了就要去解决这个知识点的掌握。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值