高可用&高并发(从架构&代码层面出发)

高可用&高并发(从架构&代码层面出发)

最近想缕缕互联网架构方面的知识,所以这里先宏观的看看关于互联网架构下的问题和相关实现,分布式架构中,我们知道最重要的就是高可用,和高并发,所以我会从这里着手。

高可用

架构可用性】:

所谓高可用就是我们在整个架构的过程中不能存在单点故障:(如果是我的服务节点在整个架构中只部署了一个,那么我们就说这个节点是单点的),当我们把只部署了一个节点,那服务器挂了,那我们的服务则是不可用状态。我们可以:

集群:所谓的集群就是把一个服务部署了多个节点,例如我们发现Tomcat不够用,那就部署多个,这就是一个例子,那说到集群就要聊一下负载,谁来对请求进行分发,采用那种方式进行请求分发。

【负载均衡】:

  • 硬件负载;F5、netscaler
  • 软件负载:Apache、Nginx、Lvs、Happrox 

那请求多了,我们我们的负载均衡的服务器也扛不住了,那我们就要对负载均衡的服务器进行集群

  • 硬件:会有一个主机和一个备机,主机和备机通过一个心跳线进行连接,如果发现备机发现主机没有心跳了,则接管主机的工作。
  • 软件:Lvs+keeplived

负载均衡算法】:随机、hash、轮询、最小连接数

常见的负载】:DNS轮询、二层负载(MAC层)、三层负载(IP层,根据传递的数据报文中的ip进行负载)、ip+端口负载(比如nginx中upstream)、七层负载(应用层负载->url的负载)

【应用层负载】:ribbon、dubbo、SpringCloud loadbalance

热备:多个节点在自己内部进行选举,当发现一个节点挂了后,其内部的选举策略会推选出新的master

  • zookeeper:zab协议
  • redis-sentinel:raft算法

多机房部署: 同城灾备、异地灾备

【应用可用性】: 

微服务的集群部署

容错性:

服务容错性:当某个服务出现错误的时候,整个系统必须正常运行,解决方法(请求隔离)

接口容错性:保证外部接口传递数据的安全性,解决办法(数据校验),以及幂等性(可能处理一个请求多次,举个例子,一个请求其实后端已经成功处理,可是调用者并不知道),解决办法(事务处理)

自我保护能力:(比如系统只能接受1000tps但是给了我2000tps)解决办法(熔断、限流、缓存、主动降级)

监控:

  • 系统资源的监控:(cpu、内存、磁盘)
  • 告警手段:发短信、邮件、电话(可以使用alertManager)
  • 应用监控:应用吞吐量、访问量(进行数据埋点、数据上报到统一的一个监控系统中)、系统的执行情况(elk)
  • 链路监控:比如一个请求经过了很多链路,我们想知道那个链路的响应时间最久(pinpoint、zipkin)

高并发

单位时间内可以同时处理的请求数量, 以下有几个名词是衡量一个系统并发的指标。

RT(response time-> 响应时间):当我们发送一个http请求后得到数据的系统响应时间,这是影响用户体验的一个重要因素

throughput(吞吐量):系统单位时间内的请求数量,通过QPS来决定的

QPSTPS(每秒的事务数、查询数):每秒同时承载的事务的处理数量 == 并发数/平均响应时间 使用 Jmeter 可以压测出

用户体验:

瀑布流、异步化、进行限额(针对支付)

架构层面

微服务

【服务进行拆分】(单个计算机的计算的性能是有限的,进行服务拆分就等于多个计算机共同工作,这样就提高了性能。)

【SLA】服务拆分后,我们可以针对重要的模块提供更大规模的集群

【数据库(关系型数据库)】 

  • 数据分片(分库分表)
  • 读写分离

【存储(非结构化存储)】:MongoDB、Redis等

【服务的无状态化设计】:当访问峰值来临,我们不得不增加服务器,但是如果增减了服务器,有时候有的数据是存储在a服务器上的,但是增加了B服务器那数据不统一如何处理

session -> Redis 数据的存储->数据库部署到第三方节点

【分布式缓存】 热点数据进行缓存

容量规划】;

【容量】指的是比如一个网站超过1000w的Page View就开始变慢,或者返回错误,那我们就认为10000w的PV就是我们网站的容量,从这几个方面进行考虑:

  • 什么时候应该加机器 、
  • 当前的吞吐量是多少、
  • 承载多少容量需要增加多少服务器

【步骤】:压测集群、节点达到一个临界值

【目标】:

  • 最大的负载状态(服务器级别的):cpu的使用率、内存的使用率、磁盘io的延时
  • 最大能接受的请求阈值:(qps、tps、错误率、平均响应时间)

【指标的收集】:压力测试 (得到更精准的数据 )、产线压测(可能传递用户真实数据进行测试)

【趋势的预测】:使用往年的数据和今年的数据增长进行一些预判(以峰值进行一个比较标准)

【扩容】:水平扩容、垂直扩容

异步化架构】::一些实时性要求不是很高的场景,我们可以通过把流量分发到mq中,从而对高并发进行一个好的处理

冗余】:增加副本、CDN内容分发网络(部署不同的节点,在不同的地方,用户距离那个地方近就访问哪个地方的节点)

【代码层面

  • 不要在循环中调用rpc
  • hashmap的初始数据,如果初始数据太小,那可能就造成了频繁的扩容,从而消耗性能
  • 数据的预热,当一些频繁使用的数据,提前进行加载(类似于恶汉模式)
  •  数据库层面,查询语句的优化,是否有索引,是否查了全表 so on
  • 异步化,线程池的使用

【客户端层面的优化】:

  • 减少请求的数量,合并请求。
  • 数据缓存,减少请求的次数

 其他的一些知识:

服务的幂等性:多次请求和一次请求对于数据的变化保持一致,就是把之前的数据重新发送了一遍,必须保证只有一个数据成功。

  • 状态机:一个数据在整个生命周期中经历的状态,比如一个订单的状态,发起、支付中、支付结束、so on,我们可以通过这个状态进行判断
  • 数据库的唯一约束、token
  • redis 当一个请求过来判断存储key和value下次来redis中进行判断。

分布式锁:我们知道synchronize和lock是解决同一进程多个线程直接的问题,但是在分布式中不是同一个进程,那就需要一个第三方的视角去判断谁可以访问某个资源,常见的分布式锁:

  • zookeeper、数据库、Redis、etcd

CAP:一致性(在集群节点中的数据一致性)、可用性(当一个请求发送后,在我可以接受的时间内,给我一个响应)、分区容错性(产生网络故障的时候,集群中的数据还是可以访问的 )

原文地址:https://www.cnblogs.com/UpGx/p/15034869.html