搜索 | 会员  
从0开始学架构
来源: 简书   作者:Finnnnnnnn  日期:2021/6/23  类别:架构设计  主题:综合  编辑:不死鸟逆
随着移动互联网的发展智能终端的普及,计算机系统早就从单机独立工作过渡到多机器协作工作。计算机以集群的方式存在,按照分布式理论的指导构建出庞大复杂的应用服务,也已经深入人心。

架构设计的目的

主要目的是为了解决软件系统复杂度带来的问题。

架构设计的三大原则

合适、简单、演化
1、合适优于业界领先
2、简单优于复杂
3、演化优于一步到位

高性能、高可用、可扩展性

高性能增加机器目的在于”扩展“处理性能;
高可用增加机器目的在于”冗余“处理单元;

高可用

”状态决策“,即系统需要能够判断当前的状态是正常还是异常,如果出现了异常就要采取行动来保证高可用。

高可用状态决策:
1、独裁式(决策者决定)
2、协商式(主从决策)
3、民主式(投票)

可扩展性

两个基本条件:正确预测变化、完美封装变化

应对变化:将“变化”封装在一个“变化层”,将不变的部分封装在一个独立的“稳定层”。

一、高性能

  • 数据库集群:读写分离、分库分表

  • NoSQL、缓存架构

  • 单服务器:PPC与TPC、Reactor与Proactor

  • 负载均衡:分类及架构、算法

(1)读写分离

读写分离的基本原理是将数据库读写操作分散到不同的节点上。

两个设计复杂度:主从复制延迟和分配机制

复制延迟

解决方法

  1. 写操作后的读操作指定发给数据库主服务器

  2. 读从机失败后再读一次主机

  3. 关键业务读写操作全部指向主机,非关键业务采用读写分离

分配机制

将读写操作区分开来,然后访问不同的数据库服务器,一般有两种方式:程序代码封装和中间件封装。

(2)分库分表

业务分库

按照业务模块将数据分散到不同的数据库服务器。比如把用户数据、商品数据、订单数据放在三台不同的数据库服务器上。

带来问题
1、join操作问题
2、事务问题
3、成本问题

分表

单表数据拆分有两种方式:垂直分表和水平分表

垂直分表:将表中某些不常用且占了大量空间的列拆分出去。
水平分表:适合表行数特别大的表。

水平分表的路由算法

1、范围路由
2、Hash路由
3、配置路由

(3)NoSQL

关系数据库存在如下缺点:

  1. 存储的是行记录,无法存储数据结构

  2. schema 扩展很不方便

  3. 在大数据场景下 I/O 较高

  4. 全文搜索功能比较弱

常见的 NoSQL 方案分为 4 类

  1. K-V 存储:解决关系数据库无法存储数据结构的问题,以 Redis 为代表。

  2. 文档数据库:解决关系数据库强 schema 约束的问题,以 MongoDB 为代表。

  3. 列式数据库:解决关系数据库大数据场景下的 I/O 问题,以 HBase 为代表。

  4. 全文搜索引擎:解决关系数据库的全文搜索性能问题,以 Elasticsearch 为代表。

(4)缓存架构

1. 缓存穿透

指缓存没有发挥作用,业务系统虽然去缓存查询数据,但缓存中没有数据,业务系统需要再次去存储系统查询数据。通常情况下有两种情况:

  1. 存储数据确实不存在

  2. 存储系统中存在数据,但缓存数据生成耗费大量时间或者资源,或刚好在业务访问的时候缓存失效了

2. 缓存雪崩

指当缓存失效(过期)后引起系统性能急剧下降的情况

缓存雪崩的常见解决方法有两种:更新锁机制和后台更新机制

1. 更新锁
对缓存更新操作进行加锁保护,保证只有一个线程能够进行缓存更新,未能获取更新锁的线程要么等待锁释放后重新读取缓存,要么就返回空值或者默认值。

2. 后台更新
由后台线程来更新缓存,而不是由业务线程来更新缓存,缓存本身的有效期设置为永久,后台线程定时更新缓存。

3. 缓存热点

缓存热点的解决方案就是复制多份缓存副本,将请求分散到多个缓存服务器上,减轻缓存热点导致的单台缓存服务器压力。

不同的缓存副本不要设置统一的过期时间,否则就会出现所有缓存副本同时生成同时失效的情况,从而引发缓存雪崩效应。正确的做法是设定一个过期时间范围,不同的缓存副本的过期时间是指定范围内的随机值。

(5)单服务器高性能模式:Reactor和Proactor

PPC 模式最主要的问题就是每个连接都要创建进程,解决这个问题是将 read 操作改为非阻塞,然后进程不断地轮询多个连接。但轮询是要消耗 CPU 的;

为了解决上述问题,只有当连接上有数据的时候进程才去处理,这就是** I/O 多路复用技术的来源**。

I/O 多路复用结合线程池,取了一个很牛的名字:Reactor

Reactor 模式的核心组成部分包括 Reactor 和处理资源池(进程池或线程池),其中Reactor 负责监听和分配事件,处理资源池负责处理事件。

Reactor 模式有这三种实现方案:

  1. 单 Reactor 单进程 / 线程。

  2. 单 Reactor 多线程。

  3. 多 Reactor 多进程 / 线程。

1. 单 Reactor 单进程 / 线程


优点:没有进程间通信,没有进程竞争,全部都在同一个进程内完成。
缺点:无法发挥多核 CPU 的性能;只能采取部署多个系统来利用多核 CPU。

只适用于业务处理非常快速的场景,目前比较著名的开源软件中使用单 Reactor 单进程的是 Redis。

2. 单 Reactor 多线程


优点:充分利用多核多 CPU 的处理能力
缺点:多线程数据共享和访问比较复杂。例如,子线程完成业务处理后,要把结果传递给主线程的 Reactor 进行发送,这里涉及共享数据的互斥和保护机制

3. 多 Reactor 多进程 / 线程


多 Reactor 多进程 / 线程的方案看起来比单 Reactor 多线程要复杂,但实际实现时反而更加简单,主要原因是:

  1. 父进程和子进程的职责非常明确,父进程只负责接收新连接,子进程负责完成后续的业务处理。

  2. 父进程和子进程的交互很简单,父进程只需要把新连接传给子进程,子进程无须返回数据。

  3. 子进程之间是互相独立的,无须同步共享之类的处理(这里仅限于网络模型相关的select、read、send 等无须同步共享,“业务处理”还是有可能需要同步共享的)。

目前著名的开源系统 Nginx 采用的是多 Reactor 多进程,采用多 Reactor 多线程的实现有Memcache 和 Netty。

(6)负载均衡

高性能集群的复杂性主要体现在需要增加一个任务分配器,现在更流行的叫法是“负载均衡器”。

常见的负载均衡系统包括 3 种:DNS 负载均衡、硬件负载均衡和软件负载均衡。

DNS 负载均衡

一般用来实现地理级别的均衡。

DNS 负载均衡的本质是 DNS 解析同一个域名可以返回不同的 IP 地址。例如,同样是 www.baidu.com,北方用户解析后获取的地址是 61.135.165.224(这是北京机房的 IP),南方用户解析后获取的地址是14.215.177.38(这是深圳机房的 IP)。

优点:就近访问,提升访问速度
缺点:更新不及时、扩展性差、分配策略比较简单

硬件负载均衡

硬件负载均衡是通过单独的硬件设备来实现负载均衡功能,这类设备和路由器、交换机类似,可以理解为一个用于负载均衡的基础网络设备。目前业界典型的硬件负载均衡设备有两款:F5 和 A10。

软件负载均衡

软件负载均衡通过负载均衡软件来实现负载均衡功能,常见的有 Nginx 和 LVS,其中Nginx 是软件的 7 层负载均衡,LVS 是 Linux 内核的 4 层负载均衡。4 层和 7 层的区别就在于协议和灵活性,Nginx 支持HTTP、E-mail 协议;而 LVS 是 4 层负载均衡,和协议无关,几乎所有应用都可以做,例如,聊天、数据库等。

负载均衡典型架构(三种组合使用)

二、高可用

(1)FMEA 方法

在架构设计领域,FMEA 的具体分析方法是:

  1. 给出初始的架构设计图。

  2. 假设架构中某个部件发生故障。

  3. 分析此故障对系统功能造成的影响。

  4. 根据分析结果,判断架构是否需要进行优化。

(2)高可用储存:双机架构

析常见的双机高可用架构:主备、主从、主备 / 主从切换和主主。

(3)高可用储存:数据集群和数据分区

数据分区

设计一个良好的数据分区架构,需要从多方面去考虑
1. 数据量:数据量的大小直接决定了分区的规则复杂度。
2. 分区规则:
3. 复制规则:

(4)异地多活架构

异地多活架构可以分为同城异区、跨城异地、跨国异地。

跨国异地:

  1. 为不同地区用户提供服务

  2. 只读类业务做多活

异地多活 - 四大技巧

  1. 优先实现核心业务的异地多活

  2. 保证核心数据最终一致性

  3. 采用多种手段同步数据(MySQL 的主备复制、Redis 的 Cluster 功能、Elasticsearch 的集群功能)

  4. 只保证绝大部分用户的异地多活

异地多活 - 四步走

第 1 步:业务分级
访问量大的业务、核心业务、产生大量收入的业务

第 2 步:数据分类
数据量、唯一性、实时性、可丢失性、可恢复性

第 3 步:数据同步
存储系统同步、消息队列同步、重复生成

第 4 步:异常处理
多通道同步、同步和访问结合、日志记录、用户补偿

(5)应对接口级的故障

导致接口级故障的原因一般有下面几种:

  • 内部原因:程序 bug 导致死循环,某个接口导致数据库慢查询,程序逻辑不完善导致耗尽内存等。

  • 外部原因:黑客攻击、促销或者抢购引入了超出平时几倍甚至几十倍的用户,第三方系统大量请求,第三方系统响应缓慢等。

解决接口级故障的核心思想和异地多活基本类似:优先保证核心业务和优先保证绝大部分用户

应对接口级的故障方法:
1. 降级:系统将某些业务或者接口的功能降低,可以是只提供部分功能,也可以是完全停掉所有功能。
2. 熔断:降级的目的是应对系统自身的故障,而熔断的目的是应对依赖的外部系统故障的情况。
3. 限流:只允许系统能够承受的访问量进来,超出系统访问能力的请求将被丢弃。
4. 排队:限流的一个变种,限流是直接拒绝用户,排队是让用户等待一段时间

三、可扩展性

可扩展的基本思想:

常见的拆分思路有如下三种:

  • 面向流程拆分:分层架构,将整个业务流程拆分为几个阶段,每个阶段作为一部分。

  • 面向服务拆分:SOA、微服务,将系统提供的服务拆分,每个服务作为一部分。

  • 面向功能拆分:微内核架构,将系统提供的功能拆分,每个功能作为一部分。

微服务

  1. 服务发现、服务路由、服务容错:这是最基本的微服务基础设施。

  2. 接口框架、API 网关:主要是为了提升开发效率,接口框架是提升内部服务的开发效率,API 网关是为了提升与外部服务对接的效率。

  3. 自动化部署、自动化测试、配置中心:主要是为了提升测试和运维效率。

  4. 服务监控、服务跟踪、服务安全:主要是为了进一步提升运维效率。

微内核架构

微内核架构,也被称为插件化架构,是一种面向功能进行拆分的可扩展性架构

微内核架构包含两类组件:核心系统和插件模块

核心系统负责和具体业务功能无关的通用功能,例如模块加载、模块间通信等;插件模块负责实现具体的业务逻辑,例如专栏前面经常提到的“学生信息管理”系统中的“手机号注册”功能。

德仔网尊重行业规范,每篇文章都注明有明确的作者和来源;德仔网的原创文章,请转载时务必注明文章作者和来源:德仔网;
头条那些事
大家在关注
我们的推荐
也许感兴趣的
干货
了解一下吧