架构之路-理论知识

前言

架构发展历史

架构历史发展中,没有放之四海而皆准的银弹

架构设计的目的是为了解决软件系统复杂度带来的问题

系统,模块,组件,架构

系统

子系统

由一群关联个体所组成系统,多半是更大系统中一部分

模块和组件

架构

指软件系统的顶层结构,架构需要明确系统需要包含哪些个体(子系统,模块,组件)。

复杂度来源

高性能

单机复杂度

单机高性能软件中,需要考虑多进程,多线程,并发,通信等众多技术点。

集群复杂度

单机的性能最终有上限的,一个复杂系统运行单机上,所需要关注的性能点很多,相互影响,当性能问题产生时,不好定位,不好作出调整,需要考虑通过集群的任务分配,任务分解来达到性能目标。简单的系统更容易做到高性能,单任务也更容易进行扩展

高可用

系统高可用方案五花八门,本质上都是通过“冗余”来实现,通常高可用场景为计算高可用,存储高可用,通过独裁,协商,民主等状态决策方式得到决策方案。状态决策不可能万无一失,但不做高可用方案又会产生更大问题。

可扩展

通过预测变化和应对变化的方式在软件开发中缓解可扩展的问题,后者通过系统拆分变化层和稳定层,设计变化层和稳定层之间的接口,抽象和实现的隔离等方法来应对。

低成本,安全,规模

架构设计三原则

合适

合适优于业界领先,真正优秀的架构是在企业当前人力,条件,业务等约束下设计出来的,能够合理将资源整合到一起发挥最大功效,并快速落地

简单

复杂在制造领域代表先进,软件领域确代表问题。不管是结构还是逻辑带来的复杂性都无法拥抱软件的变化本质

演进

架构设计不可贪大求全,盲目照搬大公司做法,应认真分析当前业务特点,明确面临问题,合理设计,快速落地满足业务需求,运行过程不断完善架构,不断随业务演化架构。

架构设计流程

高性能数据库

读写分离

通过对数据库服务器搭建集群,一主多从结构。需要注意,主备延迟和分配机制的问题。

分库分表

按照业务模块将数据分散到不同数据库服务器,百万,千万用户规模,需要注意,join操作问题,事务问题,成本问题, 亿级用户时,单表的性能无法支撑功能的正常运行,通过垂直和水平切分的手段进行。需要注意,路由问题(范围,Hash,配置路由),join操作,count操作问题,order by问题

Nosql

关系型数据库的有很多不足:

Key-Value结构的Redis,主要缺点不支持完整ACID事务, 文档数据库Mongodb在新增字段简单,历史数据不会出错,很容易存储复杂数据。缺点是不支持事务,无法实现join操作 列式数据库按照列式存储数据,业务同时完成一行中多个列的读取,写操作,需要有特定的使用场景 全文搜索引擎,通过倒排索引的技术,建立单词到文档的索引,达到通过关键词查询文档内容

缓存

缓存穿透,缓存击穿,缓存雪崩等问题

单服务 PPC与TPC

单服务器高性能关键之一就是服务器采用的并发模型,设计两点:

PPC

每次新连接新建一个进程进行处理连接请求

此处输入图片的描述

虽然父进程fork子进程后,直接close,但是真正关闭连接是等子进程调用close后

PPC模式适用于服务连接数没那么多情况,对于成千上万并发量的缺点

prefork

提前创建进程,当连接进来时,省去fork进程的操作

此处输入图片的描述

多个子进程accept同一个socket,但一个连接只保证只有一个进程能accept成功。

TPC

每次新连接新建一个线程进行处理连接请求

此处输入图片的描述

缺点:解决了fork代价高和进程通信复杂,

prethread

提前创建线程,当连接进来时,省去fork进程的操作

常见实现方式:

有些服务器会尝试创建多个进程,每个进程创建多个线程。避免了某线程异常导致进程退出,其他进程继续提供服务

Reactor

PPC模式 如果一个进程处理多个连接时,若当前连接无数据可读,进程阻塞read操作,其他连接则会无法处理。

Reactor模式包括Reactor和处理资源池,Reactor负责监听和分配事件,资源池负责处理事件。

典型实现方案:

单Reactor单进程/线程

此处输入图片的描述

缺点:

Redis使用该模式

单Reactor多线程

此处输入图片的描述

缺点:

多Reactor多进程/线程

此处输入图片的描述

Proactor

Reactor是非阻塞同步模型,而Proactor是异步模型

此处输入图片的描述

异步I/O能充分利用DMA特性,让I/O操作与计算重叠

负载均衡

DNS负载均衡

通过地理区域进行流量负载,就近访问。提升访问速度

缺点:

硬件负载均衡

功能强大,性能强大,稳定性高,安全防护,唯一缺点就是贵,一台F5顶一台马6,Q7

软件负载均衡

万级别请求处理性能,最高几十万级别,硬件则是百万级别

一般的异地多活系统部署,请求访问会先进行地理级别DNS负载,然后是集群级别硬件负载,然后才是机器级别的软件负载

算法

轮询

算法简单,无需关注服务器本身状态

加权轮询

根据硬件配置进行轮询

负载最低优先

根据不同负载指标:连接数,HTTP请求数,CPU负载,I/O负载指标进行服务器状态感知。

缺点:复杂度上升,本身可能成为性能瓶颈

性能最优类

站在client的角度,通过一定周期内的响应时间进行采用统计等方式

缺点:不管是全统计还是采样,对于周期的判断要进行不断测试调优

Hash

将同IP或ID进行hash,适用于存在业务,会话的场景

CAP

分布式系统,涉及读写操作时,只能保证consistency,available,partition tolerance三者中两个,另外一个必须被牺牲

consistency

对某个指定客户端来说,读操作保证返回最新写操作结果

available

非故障节点合理时间返回合理响应(非错误/超时响应)

partition tolerance

出现网络分区时,系统能够继续履行职责

应该根据系统内不同数据按照不同的业务场景和要求进行分类,选择合适的CAP取舍,而不是整个系统都是同一个策略

ACID是数据库事务完整性理论,CAP是分布式系统设计理论,BASE是CAP中AP理论的延伸

FMEA

故障模式和影响分析

分析方法:

FMEA分析表

高可用存储

主备,主从,主主

主备

主备模式,备机只做备份,双方只进行数据复制,主备切换需要人工操作

主从

主备模式,从机多只负责读操作,客户端需感知主从,不同操作发给不同机器,主机故障,读业务还可继续运行, 写业务不可用,需要人工干预修复。主从延迟过大,会出现过期读问题

主备/从切换

双机切换解决了主机故障无法进行写操作,主动切换主机角色

主主

主主复制对数据设计有严格的要求,如:用户生成主键ID,商品库存扣减等。一般适用于临时性,可丢失,可覆盖数据场景

数据集群分为数据集中集群数据分散集群,前者跟上面提到主从,主备一样,后者对于数据的均衡性,容错性,可伸缩性有设计要求,需要有一个角色进行数据分配

数据分区:通过将数据按照一定规则进行分布到不同地理位置的分区上,规避地理级别故障。

分区复制规则:

高可用计算

高可用架构设计基本都是通过增加更多服务器来支持。计算高可用关键点:任务管理

任务管理

主备

主机执行计算任务,主机故障,系统不可用,主机若恢复,任务分配器继续分发任务到主机;主机若不能恢复,需人工备机升主机。(冷备,温备)

主从

任务分配器根据分类分配任务到主机,从机。和主备区别时从机也执行任务,主机故障,任务管理器继续发送到主机,不管是否成功。主机支持自动恢复。不能恢复还是需要人工操作从升主

集群

为了使系统自动完成切换操作,我们采用集群方式

对称集群

也称负载均衡集群

非对称集群

不同服务器角色不同,执行任务类型不同

异地多活

采用多种手段,保证大部分用户核心业务异地多活

地理位置不同系统提供业务服务,某地方业务异常,通过人工干预,将备机变活,用户能访问其他地方正常业务系统。但是系统复杂度提升,成本会上升

跨城异地技巧

跨城异地设计步骤

接口故障处理

接口故障常由于系统压力大,负载高等引发其他后续问题

处理方案

可扩展架构

可扩展和高可用一样设计方法很多,但总结一个字“拆”

常见拆分思路

不同拆分方式,本质上决定系统扩展方式

分层结构的约束,强制将分层依赖限定为两两依赖,降低整体系统复杂度。代价就是冗余。不管业务多简单,每层都需处理

SOA需要依靠ESB实现各系统间的协议切换,数据转换,透明动态路由,引入了复杂性。用于整合多个系统

SOA与微服务

微服务注意事项

  1. 服务划分过细,服务间关系复杂。单个服务复杂度下降,整体系统复杂度提高
  2. 服务数量多,团队效率下降
  3. 调用链太长,性能下降,问题定位困难
  4. 没有自动化支撑,无法快速交付
  5. 没有服务治理,管理混乱

微服务经典实践

  1. 服务粒度:开发,设计阶段,三个人负责一个微服务;维护阶段,一个人可维护多个微服务
  2. 基于业务逻辑拆分:从业务逻辑上粗粒度,细粒度都可,如:商品,交易,用户或订单,支付,物流,卖家,买家。从三个火枪手,确定合适的拆分粒度,避免过度拆分
  3. 基于可扩展:对系统中业务模块进行稳定性排序。稳定的粒度可粗一些,不稳定粒度可细一些
  4. 基于可靠性:对系统中业务模块进行可靠性排序,重点保证核心服务的高可用
  5. 基于性能拆分:将性能要求高和性能压力大模块拆分出来

微服务基础服务

微内核

面向功能进行拆分,也被称为插件化架构。

OSGI逻辑架构图

技术演进

企业业务可分为两类,产品类,服务类,前者技术创新推动业务如:iPhone,AlphaGO;发展;后者业务发展推动技术发展如:TB,微信

不同时期的技术演进需要根据业务复杂性(初创,发展,堆功能,优化期,架构期,竞争期,成熟期,平台,服务化),用户规模(性能,可用性)等考虑

互联网公司大部分技术点

架构重构

有的放矢

架构重构要有的放矢,通常架构不满足业务时,系统各种问题频发,架构重构分析,导出都是问题,需要从纷繁复杂问题中识别真正需要架构重构解决的问题,集中力量快速解决

如:后台管理系统重构,解决不合理的耦合,单点等问题,开发效率等问题

合纵连横

运筹帷幄

先救火,后优化,再重构的分段实施做法

开源项目选择

  1. 是否满足业务,如:1000TPS需求,不应选择难度更大的,但性能更好的技术。遵循合适原则和演化原则
  2. 技术是否成熟,从版本号,使用公司数量,社区活跃度
  3. 运维能力,不应只聚焦于性能,可用性,功能等指标。还应考虑,日志是否齐全,是否有命令行,管理控制台等维护工具,是否有故障检测和恢复能力。

开源项目使用

  1. 深入研究,仔细测试。通过阅读设计文档,白皮书,核对每个配置项作用,多种场景性能测试,压力测试,观察指标,故障测试
  2. 小心应用,灰度发布。先应用非核心业务,有经验后慢慢扩展
  3. 做好应急,以防万一。对应重要数据和业务的功能使用开源技术时,要有成熟的方案做备份