i-hard-working

分布式架构知识体系

注:本文转自“后端技术精选”微信公众号。2019-02-17

https://www.douban.com/note/695644758/

1. 问题

  • 何为分布式、何为微服务
  • 为什么需要分布式
  • 分布式核心理论基础,节点、网络、时间、顺序、一致性
  • 分布式系统有哪些设计模式
  • 分布式有哪些类型
  • 如何实现分布式

2. 关键词

节点、时间、一致性、CAP、ACID、BASE、P2P、机器伸缩、网络变更、负载均衡、限流、鉴权、服务发现、服务编排、降级、熔断、幂等、分库分表、分片分区、自动运维、容错处理、全栈监控、故障恢复、性能调优

3. 全文概要

随着移动互联网的发展、智能终端的普及,计算机系统早就从单机独立工作过渡到多机器协作工作。计算机以集群的方式存在,按照分布式理论的指导构建出庞大复杂的应用服务,也已经深入人心。

本文力求从分布式基础理论、架构设计模式、工程应用、部署运维、业界方案这几大方面,介绍基于MSA(微服务架构)的分布式的知识体系大纲。从而对SOA到MSA进化有个立体的认识,从概念上和工具应用上更进一步了解微服务分布式的本质,身临其境地感受如何搭建全套微服务架构的过程。

4. 基础理论

4.1 SOA到MSA的进化

1)SOA面向服务架构:

由于业务发展到一定程度后,需要对服务进行解耦,进而把一个单一的大系统按逻辑拆分成不同的子系统,通过服务接口来通讯,面向服务的设计模式,最终需要总线集成服务,而且大部分时候还共享数据库,出现单点故障的时候会导致总线层面的故障,更进一步可能会把数据库拖垮,所以才有了更加独立的设计方案的出现。

 

2)MSA微服务架构:

微服务是真正意义上的独立服务,从服务入口到数据持久层,逻辑上都是独立隔离的,无需服务总线来接入,但同时增加了整个分布式系统的搭建和管理难度,需要对服务进行编排和管理,所以伴随着微服务的兴起,微服务生态的整套技术栈也需要无缝接入,才能支撑起微服务的治理理念。

4.2 节点与网络

1)节点:

传统的节点也就是一台单体的物理机,所有的服务都揉进去包括服务和数据库;随着虚拟化的发展,单台物理机往往可以分成多台虚拟机,实现资源利用的最大化,节点的概念也变成单台虚拟机上的服务;近几年容器技术逐渐成熟后,服务已经彻底容器化,也就是节点只是轻量级的容器服务。总体来说,节点就是能提供单位服务的逻辑计算资源的集合。

2)网络:

分布式架构的根基就是网络,不管是局域网还是公网,没有网络就无法把计算机联合在一起工作。但是网络也带了了一系列的问题。网络消息的传播有先后,消息的丢失和延迟是经常发生的事情,我们定义了三种网络工作模式:

i)同步网络:节点同步执行、消息延迟有限、高效全局锁

ii)半同步网络:锁范围放宽

iii)异步网络:节点独立执行、消息延迟无上限、无全局锁、部分算法不可行

常用网络传输层有两大协议:tcp协议和udp协议

4.3 时间与顺序

1)时间:

慢速物理时空中,时间独自在流淌着,对于串行的事务来说,很简单的就是跟着时间的脚步走即可,先来后到地发生。而后我们发明了时钟来刻画以往发生的时间点,时钟让这个世界井然有序。但是对于分布式世界来说,跟时间打交道着实是一件痛苦的事情。

分布式世界里面,我们要协调不同节点之间的先来后到关系,但是不同节点本身承认的时间又各执己见,于是我们创造了网络时间协议(NTP)试图来解决不同节点之间的标准时间,但是NTP本身表现并不尽如人意,所以我们又构造出了逻辑时钟,最后改进为向量时钟。

2)逻辑时钟:

i):定义事件先来后到

ii):t’= max(t, t_msg+1)

3)向量时钟:

t_i\' = max(t_i,t_msg_i) 

4)原子钟:

5)顺序:

有了衡量时间的工具,解决顺序问题自然就水到渠成了。因为整个分布式的理论基础就是如何协调不同节点的一致性问题,而顺序则是一致性理论的基本概念。

4.4 一致性理论

说到一致性理论,我们必须看一张关于一致性强弱对系统建设影响的对比图:

 

该图对比了不同一致性算法下的事务、性能、错误、延迟的平衡。

1)强一致性ACID:

单机环境下我们对传统关系型数据库有严苛的要求,由于存在网络的延迟和消息丢失,ACID便是保证事务的原则,这四大原则甚至我们都不需要解释出来就耳熟能详了:

i) Atomicity:原子性,一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。

ii) Consistency:一致性,在事务开始之前和事务结束以后,数据库的完整性没有被破坏。

iii) Isolation:隔离性,数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。

iv) Durabilit:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

2)分布式一致性CAP:

分布式环境下,我们无法保证网络的正常连接和信息的传送,于是发展出了CAP/FLP/DLS这三个重要的理论:

i) CAP:分布式计算系统不可能同时确保一致性(Consistency)、可用性(Availablity)和分区容忍性(Partition)。

ii) FLP:在异步环境中,如果节点间的网络延迟没有上限,只要有一个恶意的节点存在,就没有算法能在有限的时间内达成共识。

iii) DLS:

   iii-1) : 在一个部分同步网络的模型(也就是说:网络延时有界限但是我们并不知道在哪里)下运行的协议可以容忍1/3任意(换句话说,拜占庭)错误。

   iii-2) : 在一个异步模型中的确定性的协议(没有网络延时上限)不能容错(不过这个论文没有提起随机化算法可以容忍1/3的错误)。

   iii-3) : 同步模型中的协议(网络延时可以保证小于已知的时间)可以令人吃惊地达到100%容错,虽然对1/2的节点出错可以发生的情况有所限制。

3)最终一致性BASE:

多数情况下,其实我们也并非要求强一致性,部分业务可以容忍一定程度的延迟一致,所以为了兼顾效率,发展出了最终一致性理论BASE,BASE是指基本可用(Basically Available)、软状态(Soft State)、最终一致性(Eventual Consistency)。

i):基本可用(Basically Available):基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。

ii):软状态(Soft State):指允许系统存在中间状态,该中间状态不会影响系统整体可用性。分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时

                                  就是软状态的体现。

iii):最终一致性(Eventual Consistency):指系统中所有数据副本经过一定时间后,最终能够达到一致的状态。最终一致性是弱一致性的一种特殊情况。

4)一致性算法:

分布式架构的核心就在一致性的实现和妥协,那么如何设计一套算法来保证不同节点之间的通信和数据达到无限趋向一致性,就非常重要了。保证不同节点在充满不确定性网络环境下能达成相同副本的一致性是非常困难的,业界对该课题也做了大量的研究。

首先我们要了解一致性的大前提原则CALM。

CALM原则的全称是Consistency and Logical Monotonicity,主要描述的是分布式系统中单调逻辑与一致性的关系,它的内容如下,参考consistency and logical monotonicity:

i) : 在分布式系统中,单调的逻辑都能保证“最终一致性”,这个过程中不需要依赖中心节点的调度。

ii) : 任意分布式系统,如果所有的非单调逻辑都有中心节点调度,那么这个分布式系统就可以实现“最终一致性”。

然后再关注分布式系统的数据结构CRDT(Conflict-Free Replicated Data Types):

我们了解到分布式的一些规律原则之后,就要着手考虑如何来实现解决方案,一致性算法的前提是数据结构或者说一切算法的根基都是数据结构,设计良好的数据结构加上精妙的算法可以高效地解决现实的问题。经过前人不断的探索,我们得知分布式系统被广泛采用的数据结构CRDT。

参考《谈谈CRDT》:

i):基于状态:即将各个节点之间的CRDT数据直接进行合并,所有节点都能最终合并到同一个状态,数据合并的顺序不会影响到最终的结果。

ii):基于操作:将每一次对数据的操作通知给其他节点。只要节点知道了对数据的所有操作,就能合并到同一个状态。

了解数据结构后,我们需要来关注一下分布式系统的一些重要的协议HATs(Highly Available Transactions)、ZAB(Zookeeper Atomic Broadcast) :

参考《高可用事务》、《ZAB协议分析》

最后要学习的是业界主流的一致性算法,一致性算法是分布式系统最核心本质的内容,这部分的发展也会影响架构的革新,不同场景的应用也催生不同的算法:

i):Paxos:《优雅的Paxos算法》

ii):Raft:《Raft一致性算法》

iii):Gossip:《Gossip Visualization》

5. 场景分类

5.1 文件系统

单台计算机的存储始终有上限,随着网络的出现,多台计算机协作存储文件的方案也相继被提出来。最早的分布式文件系统其实也被称为网络文件系统,第一个文件服务器在1970年代被发展出来。在1976年迪吉多公司设计出File Access Listener,而现代分布式文件系统则出自Google的论文,《The Google File System》奠定了分布式文件系统的基础。现代主流分布式文件系统参考《分布式文件系统对比》,下面列出几个常用的文件系统:

i):HDFS

ii):FastDFS

iii):Ceph

iv):mooseFS

5.2 数据库

数据库当然也是属于文件系统,主数据增加了事务,检索,擦除等高级特性,所以复杂度又增加了,既要考虑数据一致性也得保证足够的性能。传统关系型数据库为了兼顾事务和性能的特性,在分布式方面的发展有限,非关系型数据库摆脱了事务的强一致性束缚,达到了最终一致性的效果,从而有了飞跃的发展,nosql也产生了多个架构的数据库类型,包括键值对存储、文档存储、列式存储:

i):KV类型:Redis

ii):文档类型:MongoDB

iii):列式存储:HBase

iv):关系型:Spanner

5.3 计算

分布式计算系统构建在分布式存储的基础上,充分发挥分布式系统的数据冗余灾备,多副本高效获取数据的特性,进而并行计算,把原本需要长时间计算的任务拆分成多个任务并行处理,从而提高了计算效率。分布式计算系统在场景上分为离线计算、实时计算和流式计算:

i) 离线:Hadoop

ii) 实时:Spark

iii) 流式:Storm、Flink/Blink

5.4 缓存

缓存作为提升性能的利器无处不在,小到cpu缓存架构,大到分布式应用存储。分布式缓存系统提供了热点数据的随机访问机制,大大提升了访问时间,但是带来的问题是如何保证数据的一致性?于是引入分布式锁来解决这个问题,主流的分布式存储系统基本就是Redis了:

i) 持久化:Redis

ii) 非持久化:Memcached

5.5 消息

分布式消息队列系统是消除异步带来一系列复杂步骤的一大利器,多线程高并发场景我们常常要谨慎地去设计业务代码,来保证多线程并发情况下不出现资源竞争导致的死锁问题。而消息队列以一种延迟消费的模式将异步任务都存到队列,然后再逐个消化:

i):Kafka

ii):RabbitMQ

iii):RocketMQ

iv):ActiveMQ

5.6 监控

分布式系统从单机到集群的形态发展,复杂度也大大提高,所以对整个系统的监控也是必不可少。

i)Zookeeper

5.7 应用

分布式系统的核心模块就是在应用如何处理业务逻辑,应用直接的调用依赖于特定的协议来通信,有基于RPC协议的也有基于通用的HTTP协议。

i) HSF

ii) Dubbo

5.8 日志

错误对于分布式系统是家常便饭,而且我们设计系统的时候本身就需要把容错作为普遍存在的现象来考虑。那么当出现故障的时候,快速恢复和排查故障就显得非常重要了。分布式日志采集存储和检索则可以给我们提供有力的工具来定位请求链路中出现问题的环节。

i) 日志采集:flume

ii) 日志存储:ElasticSearch/Solr、SLS

iii) 日志定位:Zipkin

5.9 账本

之前我们提到的所谓分布式系统,是迫于单机的性能有限,而堆硬件却又无法无休止地增加,于是什么才采用了多台计算机来干同样的活,但是这样的分布式系统始终需要中心化的节点来监控或者调度系统的资源,即使该中心节点也可能是多节点组成。而区块链则是真正的去中心化分布式系统,系统里面有P2P网络协议各自通信,没有真正意义的中心节点,彼此按照区块链节点的算力、权益等机制来协调新区块的产生。

i) 比特币

ii) 以太坊

6. 设计模式

6.1 可用性

可用性是系统运行和工作的时间比例,通常以正常运行时间的百分比来衡量。它可能受系统错误、基础架构、恶意攻击和系统负载的影响。分布式系统通常为用户提供服务级别协议(SLA),因此应用程序必须设计为最大化可用性:

i) 健康检查:系统实现全链路功能检查,外部工具定期通过公开端点访问系统。

ii) 负载均衡:使用队列起到削峰作用,作为请求和服务之间的缓冲区,以平滑间歇性的重负载。

iii) 节流:限制应用级别、租户或整个服务所消耗资源的范围。

6.2 数据管理

数据管理是分布式系统的关键要素,并影响大多数质量的属性。由于性能、可扩展性或可用性等原因,数据通常托管在不同位置和多个服务器上,这可能带来一系列挑战。例如必须维护数据一致性、并且通常需要跨不同位置同步数据:

i) 缓存:根据需要将数据从数据存储层加载到缓存。

ii) CQRS(Command Query Responsibility Segregation):命令查询职责分离。

iii) 事件溯源:仅使用追加方式记录域中完整的系列事件。

iv) 索引表:在经常查询引用的字段上创建索引。

v) 物化视图:生成一个或多个数据预填充视图。

vi) 拆分:将数据拆分为水平的分区或分片。

6.3 设计与实现

良好的设计包括诸如组件设计和部署的一致性,简化管理和开发的可维护性,以及允许组件和子系统用于其他应用程序和其他方案的可重用性等因素。在设计和实施阶段作出的决策对分布式系统服务质量和总体拥有成本产生巨大影响:

1) 代理:反向代理

2) 适配器:在现代应用程序和遗留系统之间实现适配器层

3) 前后端分离:后端服务提供接口供前端应用程序调用

4) 计算资源整合:将多个相关任务或操作合并到一个计算单元中

5) 配置分离:将配置信息从应用程序部署包中移出到配置中心

6) 网关聚合:使用网关将多个单独的请求聚合到一个请求中

7) 网关卸载:将共享或专用服务功能卸载到网关代理

8) 网关路由:使用单个端点将请求路由到多个服务

9) 领导人选举:通过选择一个实例作为负责管理其他实例的管理员,协调分布式系统的云

10) 管道和过滤器:将复杂的任务分解为一系列可以重复使用的单独组件

11) 边车:将应用的监控组件部署到单独的进程或容器中,以提供隔离和封装

12) 静态内容托管:将静态内容部署到CDN,加速访问效率

6.4 消息

分布式系统需要一个连接组件和服务的消息传递中间件,理想情况是以松散耦合的方式,以便最大限度地提高可伸缩性。异步消息传递被广泛使用,并提供许多好处,但也带来了诸如消息排序、幂等性挑战

i) 竞争消费者:多线程并发消费

ii) 优先级队列:消息队列分优先级、优先级高的先被消费

6.5 管理与监控

分布式系统在远程数据中心运行,无法完全控制基础结构,这使得管理和监控比单机部署更困难。应用必须公开运行时信息,管理员可以使用这些信息来管理和监视系统,以及支持不断变化的业务需求和自定义,而无需停止或重新部署。

6.6 性能与扩展

性能表示系统在给定时间间隔内执行任何操作的响应性,而可伸缩性是系统处理负载增加而不影响性能或容易增加可用资源的能力。分布式系统通常会遇到变化的负载和活动高峰,特别是在多租户场景中,几乎是不可能预测的。相反,应用应该能够在限制范围内扩展以满足需求高峰,并在需求减少时进行收缩。可伸缩性不仅涉及计算实例,还涉及其他元素,如数据存储、消息队列等。

6.7 弹性

弹性是指系统能够优雅地处理故障并从故障中恢复。分布式系统通常是多租户,使用共享平台服务,竞争资源和带宽,通过Internet进行通信,以及在商用硬件上运行,意味着出现瞬态和更永久性故障的可能性增加。为了保持弹性,必须快速有效地检测故障并进行恢复。

1)隔离:将应用程序的元素隔离到池中,以便在其中一个失败时,其他元素将继续运行。

2)断路器:处理连接到远程服务或资源时可能需要不同时间修复的故障。

3)补偿交易:撤销一系列步骤执行的工作,这些步骤共同定义最终一致的操作。

4)健康检查:系统实现全链路功能检查,外部工具定期通过公开端点访问系统。

5)重试:通过透明地重试先前失败的操作,使应用程序在尝试连接到服务或网络资源时处理预期的临时故障。

6.8 安全

安全性是系统能够防止在设计使用之外的恶意或意外行为,并防止泄漏或丢失信息。分布式系统在受信任的本地边界之外的Internet上运行,通常向观众开放,并且可以为不受信任的用户提供服务。必须以保护应用程序免受恶意攻击,限制仅允许对已批准用户的访问,并保护敏感数据。

1)联合身份:将身份验证委派给外部身份提供商。

2)看门人:通过使用专用主机实例来保护应用程序和服务,该实例充当客户端与应用程序或服务之间的代理,验证和清理请求,并在它们之间传递请求和数据。

3)代课钥匙:使用为客户端提供对特定资源或服务的受限直接访问的令牌或密钥。

7. 工程应用

7.1 资源调度

7.2 流量调度

7.3 服务调度

7.4 数据调度

7.5 自动化运维

7.6 容错处理

7.7 全栈监控

7.8 故障恢复

7.9 性能调优

8. 总结

分类:

技术点:

相关文章: