本文主要介绍互联网架构中的高可用及负载均衡,参考文章高可用、负载均衡、异构负载均衡
高可用HA(High Availability)是在互联网架构设计中必须考虑。高可用是指通过设计来减少系统不能提供服务的时间。
高可用实现的核心思想是冗余和故障自动转移。
下面是典型的互联网分层架构:
下面我们看看各层怎么实现高可用。
客户端 -> 反向代理层
通过反向代理层的冗余来实现。这里以nginx为例,提供多个nginx,对外使用统一的VIP,并使用keepalived进行存活探测。当一台nginx挂掉,keepalived将流量导向shadow nginx,从而实现高可用。
反向代理层 -> 站点层
通过站点层冗余来实现高可用。nginx.conf里能够配置多个web后端,并且nginx能够探测到多个后端的存活性。当一个web server挂掉,nginx能探测到并自动进行故障转移,将流量导向其他web server。
站点层 -> 服务层
站点层到服务层的高可用通过服务层的冗余来实现的。“服务连接池”会与多个下游服务建立连接,每次请求会“随机”选取连接来访问下游服务。服务连接池能够自动进行故障转移。
服务层 -> 缓存层
服务层到缓存层的高可用通过缓存数据的冗余来实现,方法分为缓存双读写或者支持主从同步的缓存集群来实现。注意:缓存层并不一定要求高可用,只是为了加快访问DB速度。
缓存双读写:
主从同步的缓存集群:redis支持master-slave,并使用redis sentinel来做监控master,slave节点的存活性,自动故障转移以及master promotion。
服务层 -> 数据库层
服务层到数据库层的高可用是通过数据库的冗余来实现,包括主从复制,DB sharding,联合,冗余设计。使用keepalived存活探测并使用相同VIP提供服务。
知识点插入=========>
对于订单交易,包含seller和buyer两个方面。若使用分库分表,使用seller_id分库分表,则查询buyer_id需要查询所有数据库;反之,亦然。这时,可以分别创建2个表T1和T2,分别seller_id和buyer_id来分库分表。
T(buyer_id, seller_id, oid);
//数据冗余满足不同查询需求
T1(buyer_id, seller_id, oid)
T2(seller_id, buyer_id, oid)
对于数据冗余,如何保证一致性?
- 服务同步双写 一致性比较高,但单写变双写,时间长,而且有可能不一致;
- 服务异步双写 请求处理时间短,但增加了MQ,且消息的异步性使得数据短时间不一致;
检查数据是否一致:
- 线下全量数据扫描;
- 线下增量数据扫描;
- 线上实时检查消息对;
<===============
高可用通过冗余来实现,但为了充分利用资源,需要在使用资源时达到负载均衡。负载均衡是指请求和数据均匀分摊到每个操作单元上。
我们依然使用上面的互联网架构并介绍每层时怎么做到负载均衡。
客户端 -> 反向代理层
客户端到反向代理层的负载均衡通过DNS轮询实现。每个域名对应一组IP,通过DNS轮询,使得每个IP被均衡访问。这些IP时nginx的外网IP。
反向代理层 -> 站点层
反向代理层到站点层的负载均衡以nginx为例,配置nginx的配置文件nginx.conf,可以实现多种负载均衡策略,包括:(加权)随机法、(加权)请求轮询、少连接路由、ip-hash、一致性hash。其中,ip-hash使得来自相同ip的请求被路由同一个server,从而可保存session,但对于server增减扩展不好。一致性hash利用hash环来解决这个问题。
站点层 -> 服务层
站点层到服务层的负载均衡通过服务连接池来实现。同时,服务连接池还具有故障转移、超时处理、限流限速、ID串行化等诸多功能。
数据层
数据量很大的情况下,数据会被水平切分,分散在不同DB。数据层的负载均衡包括请求和数据两方面。数据负载均衡是指数据被均匀存储,而请求负载均衡是指数据访问均匀落到每个数据库。
数据水平切分的方法:按range水平切分和按id-hash水平切分。前者的好处是划分简单、数据分布均衡,冗余扩展;但数据请求不一定均衡。后者能够同时实现数据和请求的均衡,但扩展性不好。
=================
负载均衡另一个需要关注的是异构系统之间的负载均衡以及过载保护。
在异构系统之间实现负载均衡可以静态或动态地进行负载调度来实现。
方法1: 根据service处理能力为每个service设置静态权重来标识该service处理请求的概率
该方法简单,但缺点是权重固定,无法动态调整。
方法2:使用动态权重来标识service处理能力
该方法根据service处理请求的能力来动态调整权重。如:权重初始化为60,成功处理一个请求,权重加1,超时处理一个请求,权重减10,权重范围为0-100.
过载保护
随着外部负载的不断升高,系统实际处理负载会增加,当外部负载升高到一个临界值,系统会被压垮,实际处理能力会降为0。
过载保护,是指当外部负载超过系统处理能力时,系统会进行自我保护,依然能对外提供有损的稳定服务。
方式1:通过“静态权重”标识service的处理能力
当负载超出系统的处理能力,全部抛弃。
方式2:借助“动态权重”来实施过载保护
当系统疑是过载时,采取一定策略来减轻系统的压力,如:超时3次后,休息1s,若动态权重变为0,则休息1分钟。
注意:如果过载保护仍处理不了所有请求,只能抛弃一些请求来放在系统崩溃。