• 高并发、高性能、高可用的理解及处理方式



    首先要明确的一个概念是: 高并发是根因,而高性能和高可用是结果

    通俗点来说,就是指为了解决高并发这一现象,怎么做,才能保证系统的高性能和高可用?

    系统在巨大的流量洪峰(即指高并发场景)冲击下,依然能高效、稳定、正常地(即指高性能、高可用)对外提供服务,这是系统设计的主要目标之一。

    具体的指标定义,如:高并发方面要求 QPS(Queries Per Second,每秒查询率) 大于 10 万,高性能方面要求请求延迟小于 100 ms,高可用方面要高于 99.99%。

    1. 高并发

    高并发问题:如果百万级别、千万级别甚至上亿级别的访问请求同时到来,系统怎么快速处理这些请求且能保证系统不崩溃?

    基于上面的问题,从请求入口开始分析处理一个请求要用到哪些策略或者技术、方式。

    1.1 负载均衡

    当请求到来时,给到哪个服务去处理?这里涉及到请求的分发问题,采用负载均衡的方式处理,那么其对应的应用部署方式就得是集群化部署了。

    1.2 池化技术

    处理请求,由于请求多,做阻塞式处理肯定不行,因此采用多线程处理。

    而多线程处理时如果涉及顺序问题或者一致性问题,要考虑对资源加锁处理。

    线程的创建,需要消耗时间、消耗内存、消耗 CPU ,总结就是有开销,特别是大量创建线程时,开销更大;因此为了解决这个问题,用到池化技术

    池化技术包括:线程池、连接池、内存池、对象池、协程池、进程池等

    1.3 流量过滤

    做好前置校验,对于非法的、不符合要求的请求,设计好过滤器进行过滤,在进行真正的业务逻辑处理之前,先对流量过滤一轮,减少并发压力。

    过滤器:设计一套自己的规则,对过来的请求进行校验(如校验IP、校验请求参数是否合法等),如果不符合要求,直接拒绝,不进行后面的处理。

    2. 高性能

    系统性能不好,直接导致的问题就是处理请求耗时长,用户等待时间长,用户体验差。

    系统性能影响的因素:

    • 用户网络环境
    • 请求/响应的数据包大小
    • 业务系统 CPU、内存、磁盘等性能
    • 业务链路的长度
    • 关系方系统的性能
    • 处理逻辑的代码实现是否高效… 等等

    怎么提高系统的性能?

    2.1 使用缓存

    高并发场景下,对于查询操作,每次都去查数据库,会给数据库造成很大压力,导致性能下降,严重的直接就宕机了,所以这是要避免的,需要引入缓存,比如用 Redis 、MemCache去做缓存处理。

    查询的时候,先去缓存中读,如果有结果就直接返回,没有再去数据库查,减少直接访问数据库的次数,并且读缓存的效率是比读数据库要高的。

    2.2 磁盘问题处理

    实际开发中,我们经常会在一些关键的地方,写上日志的打印语句,方便定位并排查问题。

    不打日志的人,不是好人,绝非善类,十有八九是个坑爹的货,机智的你要知道速速远离。

    我们打印出来的日志,最终还是会写到磁盘上保存起来,这里就涉及到了磁盘的 IO 读写问题。

    不仅仅是写日志,包括其它涉及直接读或者写磁盘上文件的操作,都会有相同的问题。

    磁盘读写的效率肯定是低于 CPU 或者 内存的处理效率的,而且磁盘本身也是有性能的问题存在。

    所以可以这么处理:

    1. 磁盘升级,选用读写性能更好的磁盘,这里是硬件层次的处理
    2. 在写文件到磁盘上时,可以考虑先写到内存上,给内存设定一个阈值,当达到阈值时再批量将内存上的文件,写到磁盘上

    3. 高可用

    系统的高可用,更多的是从架构和部署方式去着手解决。

    例如一个单体系统,所有业务模块都放到同一个系统中,当某一个模块坏掉,会导致整个系统坏掉,无法对外提供正常的服务,这就是不可用。

    如果是微服务系统,每个模块都是独立的小系统,所有小系统共同组成一个微服务系统对外提供服务,一个小系统坏掉,并不会影响到其它小系统正常运行,而整体依旧可以对外提供服务,可用性比单体的更高。

    保证系统可用性的策略或者方式,大致有下面这么些:

    3.1 采用微服务架构

    利用微服务架构,分散能力,使得各个模块独立成为一个小系统,降低系统间的耦合性,提高系统对外提供正常服务的能力。

    3.2 采用分布式+集群部署

    在高并发场景下,一个服务的部署,不应该只部署在一台服务器上,起码 3 台以上,这样,一台服务器宕机了,还有另外的服务器能正常使用并对外服务,这样就用到了集群的部署方式。

    而采用微服务架构,也不应该把每个独立的小系统都部署在同一台服务器上,一个小系统就是一台服务器,这就使用了分布式部署。

    将上面的两种部署方式结合起来用,先做分布式部署再为每个小系统拓展成为一个集群,就产生了分布式+集群部署。

    3.3 同城双活、异地多活

    这里是做灾备考虑,例如当前放置服务器的机房,由于温度过高,着火了,所有服务器都被烧掉,面对这样的情况,前面的架构设计得再好也无济于事。

    基于上面可能存在的情况,就要考虑做同城双活或者异地多活了。

    简单来说,就是多建几个同样的机房,并且这些机房分布在不同的地理位置,这样一个机房被烧掉了,另外的还能用,依旧保证了可用性。

    3.4 主从切换

    对于需要存储数据的应用,例如 Redis 、Mysql 等,做好主从复制,做好一主多从的设计和考虑,当主节点出问题时,从节点自动升级为新的主节点,对外服务。

    3.5 熔断限流

    熔断与限流,二者的目的都是提供过载保护,保证系统不至于崩溃,无法使用。

    这里的过载保护,是指负载超过系统的承载能力时,系统需要自动采取保护措施,确保自身不被压垮、崩溃。

    熔断:在系统濒临崩溃时,立即中断服务,停止所有请求的处理,保障系统稳定避免崩溃。类似于电器中的“保险丝”,当电流过大的时候,“保险丝”会先被烧掉,断开电流,以免电路过热烧毁电器引起火灾。

    限流:原理跟熔断有点类似,都是通过判断某个条件来确定是否执行某个策略。

    熔断与限流的区别:熔断,触发过载保护,该节点会暂停服务,直到恢复;限流,只处理自己能力范围之内的请求,超出范围的请求会被限流,并不会暂停服务。

  • 相关阅读:
    java任务跟踪系统
    coreldraw2024版本有哪些新增功能?
    HDI激光钻孔和常见问题
    计算机视觉+人工智能面试笔试总结——CNN模型总结
    远程桌面另一台服务器连接不上,局域网IP如何访问另一台服务器
    Android 12.0 自定义仿小米全面屏手势导航左右手势滑动返回UI效果
    EalsticSearch
    探索数据结构:从基础到高级
    PyTorch 中的乘法:mul()、multiply()、matmul()、mm()、mv()、dot()
    【ESP8266+TM1650时钟数码管+DS3231模块】制作网络时钟
  • 原文地址:https://blog.csdn.net/Crezfikbd/article/details/126682042