精华内容
下载资源
问答
  • 参考文章 大型分布式系统架构设计.架构图.演变
    展开全文
  • 分布式系统类型多,涉及面非常广,不同类型的系统有不同的特点,批量计算和实时计算就差别非常大。这篇文章中,重点会讨论下分布式数据系统的设计,比如分布式存储系统,分布式搜索系统,分布式分析系统...

    分布式系统类型多,涉及面非常广,不同类型的系统有不同的特点,批量计算和实时计算就差别非常大。

    这篇文章中,重点会讨论下分布式数据系统的设计,比如分布式存储系统,分布式搜索系统,分布式分析系统等。

    我们先来简单看下Elasticsearch的架构。

    Elasticsearch 集群架构

    Elasticsearch是一个非常著名的开源搜索和分析系统,目前被广泛应用于互联网多种领域中,尤其是以下三个领域特别突出。

    一是搜索领域,相对于solr,真正的后起之秀,成为很多搜索系统的不二之选。

    二是Json文档数据库,相对于MongoDB,读写性能更佳,而且支持更丰富的地理位置查询以及数字、文本的混合查询等。

    三是时序数据分析处理,目前是日志处理、监控数据的存储、分析和可视化方面做得非常好,可以说是该领域的引领者了。

    Elasticsearch的详细介绍可以到官网查看。我们先来看一下Elasticsearch中几个关键概念:

    • 节点(Node):物理概念,一个运行的Elasticearch实例,一般是一台机器上的一个进程。

    • 索引(Index),逻辑概念,包括配置信息mapping和倒排正排数据文件,一个索引的数据文件可能会分布于一台机器,也有可能分布于多台机器。索引的另外一层意思是倒排索引文件。

    • 分片(Shard):为了支持更大量的数据,索引一般会按某个维度分成多个部分,每个部分就是一个分片,分片被节点(Node)管理。

      一个节点(Node)一般会管理多个分片,这些分片可能是属于同一份索引,也有可能属于不同索引,但是为了可靠性和可用性,同一个索引的分片尽量会分布在不同节点(Node)上。分片有两种,主分片和副本分片。

    • 副本(Replica):同一个分片(Shard)的备份数据,一个分片可能会有0个或多个副本,这些副本中的数据保证强一致或最终一致。

    用图形表示出来可能是这样子的:

    9b932d92e3f69dcefdcd362f6426b25e.png
    图片
    • Index 1:蓝色部分,有3个shard,分别是P1,P2,P3,位于3个不同的Node中,这里没有Replica。

    • Index 2:绿色部分,有2个shard,分别是P1,P2,位于2个不同的Node中。

      并且每个shard有一个replica,分别是R1和R2。

      基于系统可用性的考虑,同一个shard的primary和replica不能位于同一个Node中。

      这里Shard1的P1和R1分别位于Node3和Node2中,如果某一刻Node2发生宕机,服务基本不会受影响,因为还有一个P1和R2都还是可用的。因为是主备架构,当主分片发生故障时,需要切换,这时候需要选举一个副本作为新主,这里除了会耗费一点点时间外,也会有丢失数据的风险。

    Index流程

    建索引(Index)的时候,一个Doc先是经过路由规则定位到主Shard,发送这个doc到主Shard上建索引,成功后再发送这个Doc到这个Shard的副本上建索引,等副本上建索引成功后才返回成功。

    在这种架构中,索引数据全部位于Shard中,主Shard和副本Shard各存储一份。当某个副本Shard或者主Shard丢失(比如机器宕机,网络中断等)时,需要将丢失的Shard在其他Node中恢复回来,这时候就需要从其他副本(Replica)全量拷贝这个Shard的所有数据到新Node上构造新Shard。

    这个拷贝过程需要一段时间,这段时间内只能由剩余主副本来承载流量,在恢复完成之前,整个系统会处于一个比较危险的状态,直到failover结束。

    这里就体现了副本(Replica)存在的一个理由,避免数据丢失,提高数据可靠性。副本(Replica)存在的另一个理由是读请求量很大的时候,一个Node无法承载所有流量,这个时候就需要一个副本来分流查询压力,目的就是扩展查询能力。

    角色部署方式

    接下来再看看角色分工的两种不同方式:

    963cced341ba27eb41ac7c286a357aad.png
    图片

    Elasticsearch支持上述两种方式:

    1.混合部署(左图)

    • 默认方式。

    • 不考虑MasterNode的情况下,还有两种Node,Data Node和Transport Node,这种部署模式下,这两种不同类型Node角色都位于同一个Node中,相当于一个Node具备两种功能:Data和Transport。

    • 当有index或者query请求的时候,请求随机(自定义)发送给任何一个Node,这台Node中会持有一个全局的路由表,通过路由表选择合适的Node,将请求发送给这些Node,然后等所有请求都返回后,合并结果,然后返回给用户。一个Node分饰两种角色。

    • 好处就是使用极其简单,易上手,对推广系统有很大价值。最简单的场景下只需要启动一个Node,就能完成所有的功能。

    • 缺点就是多种类型的请求会相互影响,在大集群如果某一个Data Node出现热点,那么就会影响途经这个Data Node的所有其他跨Node请求。如果发生故障,故障影响面会变大很多。

    • Elasticsearch中每个Node都需要和其余的每一个Node都保持13个连接。这种情况下, - 每个Node都需要和其他所有Node保持连接,而一个系统的连接数是有上限的,这样连接数就会限制集群规模。

    • 还有就是不能支持集群的热更新。

    2.分层部署(右图):

    • 通过配置可以隔离开Node。

    • 设置部分Node为Transport Node,专门用来做请求转发和结果合并。

    • 其他Node可以设置为DataNode,专门用来处理数据。

    • 缺点是上手复杂,需要提前设置好Transport的数量,且数量和Data Node、流量等相关,否则要么资源闲置,要么机器被打爆。

    • 好处就是角色相互独立,不会相互影响,一般Transport Node的流量是平均分配的,很少出现单台机器的CPU或流量被打满的情况,而DataNode由于处理数据,很容易出现单机资源被占满,比如CPU,网络,磁盘等。独立开后,DataNode如果出了故障只是影响单节点的数据处理,不会影响其他节点的请求,影响限制在最小的范围内。

    • 角色独立后,只需要Transport Node连接所有的DataNode,而DataNode则不需要和其他DataNode有连接。一个集群中DataNode的数量远大于Transport Node,这样集群的规模可以更大。另外,还可以通过分组,使Transport Node只连接固定分组的DataNode,这样Elasticsearch的连接数问题就彻底解决了。

    • 可以支持热更新:先一台一台的升级DataNode,升级完成后再升级Transport Node,整个过程中,可以做到让用户无感知。

    上面介绍了Elasticsearch的部署层架构,不同的部署方式适合不同场景,需要根据自己的需求选择适合的方式。

    Elasticsearch 数据层架构

    接下来我们看看当前Elasticsearch的数据层架构。

    数据存储

    Elasticsearch的Index和meta,目前支持存储在本地文件系统中,同时支持niofs,mmap,simplefs,smb等不同加载方式,性能最好的是直接将索引LOCK进内存的MMap方式。

    默认,Elasticsearch会自动选择加载方式,另外可以自己在配置文件中配置。这里有几个细节,具体可以看官方文档。

    索引和meta数据都存在本地,会带来一个问题:当某一台机器宕机或者磁盘损坏的时候,数据就丢失了。

    为了解决这个问题,可以使用Replica(副本)功能。

    副本(Replica)

    可以为每一个Index设置一个配置项:副本(Replicda)数,如果设置副本数为2,那么就会有3个Shard,其中一个是PrimaryShard,其余两个是ReplicaShard,这三个Shard会被Mater尽量调度到不同机器,甚至机架上,这三个Shard中的数据一样,提供同样的服务能力。

    副本(Replica)的目的有三个:

    • 保证服务可用性:当设置了多个Replica的时候,如果某一个Replica不可用的时候,那么请求流量可以继续发往其他Replica,服务可以很快恢复开始服务。

    • 保证数据可靠性:如果只有一个Primary,没有Replica,那么当Primary的机器磁盘损坏的时候,那么这个Node中所有Shard的数据会丢失,只能reindex了。

    • 提供更大的查询能力:当Shard提供的查询能力无法满足业务需求的时候, 可以继续加N个Replica,这样查询能力就能提高N倍,轻松增加系统的并发度。

    问题

    上面说了一些优势,这种架构同样在一些场景下会有些问题。

    Elasticsearch采用的是基于本地文件系统,使用Replica保证数据可靠性的技术架构,这种架构一定程度上可以满足大部分需求和场景,但是也存在一些遗憾:

    • Replica带来成本浪费。为了保证数据可靠性,必须使用Replica,但是当一个Shard就能满足处理能力的时候,另一个Shard的计算能力就会浪费。

    • Replica带来写性能和吞吐的下降。每次Index或者update的时候,需要先更新Primary Shard,更新成功后再并行去更新Replica,再加上长尾,写入性能会有不少的下降。

    • 当出现热点或者需要紧急扩容的时候动态增加Replica慢。新Shard的数据需要完全从其他Shard拷贝,拷贝时间较长。

    上面介绍了Elasticsearch数据层的架构,以及副本策略带来的优势和不足,下面简单介绍了几种不同形式的分布式数据系统架构。

    分布式系统

    第一种:基于本地文件系统的分布式系统

    5a8c88517c7981051ff460757ef20d51.png
    图片

    上图中是一个基于本地磁盘存储数据的分布式系统。Index一共有3个Shard,每个Shard除了Primary Shard外,还有一个Replica Shard。

    当Node 3机器宕机或磁盘损坏的时候,首先确认P3已经不可用,重新选举R3位Primary Shard,此Shard发生主备切换。然后重新找一台机器Node 7,在Node7 上重新启动P3的新Replica。

    由于数据都会存在本地磁盘,此时需要将Shard 3的数据从Node 6上拷贝到Node7上。如果有200G数据,千兆网络,拷贝完需要1600秒。

    如果没有replica,则这1600秒内这些Shard就不能服务。

    为了保证可靠性,就需要冗余Shard,会导致更多的物理资源消耗。

    这种思想的另外一种表现形式是使用双集群,集群级别做备份。

    在这种架构中,如果你的数据是在其他存储系统中生成的,比如HDFS/HBase,那么你还需要一个数据传输系统,将准备好的数据分发到相应的机器上。

    这种架构中为了保证可用性和可靠性,需要双集群或者Replica才能用于生产环境,优势和副作用在上面介绍Elasticsearch的时候已经介绍过了,这里就就不赘述了。

    Elasticsearch使用的就是这种架构方式。

    第二种:基于分布式文件系统的分布式系统(共享存储)

    0bb9ed4eb16ee38eb3e90f60a0ec170e.png
    图片

    针对第一种架构中的问题,另一种思路是:存储和计算分离。

    第一种思路的问题根源是数据量大,拷贝数据耗时多,那么有没有办法可以不拷贝数据?

    为了实现这个目的,一种思路是底层存储层使用共享存储,每个Shard只需要连接到一个分布式文件系统中的一个目录/文件即可,Shard中不含有数据,只含有计算部分。

    相当于每个Node中只负责计算部分,存储部分放在底层的另一个分布式文件系统中,比如HDFS。

    上图中,Node 1 连接到第一个文件;Node 2连接到第二个文件;Node3连接到第三个文件。

    当Node 3机器宕机后,只需要在Node 4机器上新建一个空的Shard,然后构造一个新连接,连接到底层分布式文件系统的第三个文件即可,创建连接的速度是很快的,总耗时会非常短。

    这种是一种典型的存储和计算分离的架构,优势有以下几个方面:

    • 在这种架构下,资源可以更加弹性,当存储不够的时候只需要扩容存储系统的容量;当计算不够的时候,只需要扩容计算部分容量。

    • 存储和计算是独立管理的,资源管理粒度更小,管理更加精细化,浪费更少,结果就是总体成本可以更低。

    • 负载更加突出,抗热点能力更强。一般热点问题基本都出现在计算部分,对于存储和计算分离系统,计算部分由于没有绑定数据,可以实时的扩容、缩容和迁移,当出现热点的时候,可以第一时间将计算调度到新节点上。

    这种架构同时也有一个不足:访问分布式文件系统的性能可能不及访问本地文件系统。在上一代分布式文件系统中,这是一个比较明显的问题,但是目前使用了各种用户态协议栈后,这个差距已经越来越小了。HBase使用的就是这种架构方式。Solr也支持这种形式的架构。

    总结

    上述两种架构,各有优势和不足,对于某些架构中的不足或缺陷,思路不同,解决的方案也大相径庭,但是思路跨度越大,收益一般也越大。

    上面只是介绍了分布式数据(存储/搜索/分析等等)系统在存储层的两种不同架构方式,希望能对大家有用。但是分布式系统架构设计所涉及的内容广,细节多,权衡点众,如果大家对某些领域或者方面有兴趣,也可以留言,后面再探讨。

    展开全文
  • 本文来说下如何从Elasticsearch来看分布式系统架构设计 文章目录概述 概述 分布式系统类型多,涉及面非常广,不同类型的系统有不同的特点,批量计算和实时计算就差别非常大。这篇文章中,重点会讨论下分布式数据...

    本文来说下如何从Elasticsearch来看分布式系统架构设计


    概述

    分布式系统类型多,涉及面非常广,不同类型的系统有不同的特点,批量计算和实时计算就差别非常大。这篇文章中,重点会讨论下分布式数据系统的设计,比如分布式存储系统,分布式搜索系统,分布式分析系统等

    我们先来简单看下Elasticsearch的架构。

    在这里插入图片描述


    ES集群架构

    Elasticsearch是一个非常著名的开源搜索和分析系统,目前被广泛应用于互联网多种领域中,尤其是以下三个领域特别突出。一是搜索领域,相对于solr,真正的后起之秀,成为很多搜索系统的不二之选。二是Json文档数据库,相对于MongoDB,读写性能更佳,而且支持更丰富的地理位置查询以及数字、文本的混合查询等。三是时序数据分析处理,目前是日志处理、监控数据的存储、分析和可视化方面做得非常好,可以说是该领域的引领者了。

    Elasticsearch的详细介绍可以到官网查看。我们先来看一下Elasticsearch中几个关键概念:

    • 节点(Node):物理概念,一个运行的Elasticearch实例,一般是一台机器上的一个进程。
    • 索引(Index),逻辑概念,包括配置信息mapping和倒排正排数据文件,一个索引的数据文件可能会分布于一台机器,也有可能分布于多台机器。索引的另外一层意思是倒排索引文件。
    • 分片(Shard):为了支持更大量的数据,索引一般会按某个维度分成多个部分,每个部分就是一个分片,分片被节点(Node)管理。一个节点(Node)一般会管理多个分片,这些分片可能是属于同一份索引,也有可能属于不同索引,但是为了可靠性和可用性,同一个索引的分片尽量会分布在不同节点(Node)上。分片有两种,主分片和副本分片。
    • 副本(Replica):同一个分片(Shard)的备份数据,一个分片可能会有0个或多个副本,这些副本中的数据保证强一致或最终一致。

    用图形表示出来可能是这样子的:

    在这里插入图片描述

    • Index 1:蓝色部分,有3个shard,分别是P1,P2,P3,位于3个不同的Node中,这里没有Replica。
    • Index 2:绿色部分,有2个shard,分别是P1,P2,位于2个不同的Node中。并且每个shard有一个replica,分别是R1和R2。基于系统可用性的考虑,同一个shard的primary和replica不能位于同一个Node中。这里Shard1的P1和R1分别位于Node3和Node2中,如果某一刻Node2发生宕机,服务基本不会受影响,因为还有一个P1和R2都还是可用的。因为是主备架构,当主分片发生故障时,需要切换,这时候需要选举一个副本作为新主,这里除了会耗费一点点时间外,也会有丢失数据的风险。

    Index流程

    建索引(Index)的时候,一个Doc先是经过路由规则定位到主Shard,发送这个doc到主Shard上建索引,成功后再发送这个Doc到这个Shard的副本上建索引,等副本上建索引成功后才返回成功。

    在这种架构中,索引数据全部位于Shard中,主Shard和副本Shard各存储一份。当某个副本Shard或者主Shard丢失(比如机器宕机,网络中断等)时,需要将丢失的Shard在其他Node中恢复回来,这时候就需要从其他副本(Replica)全量拷贝这个Shard的所有数据到新Node上构造新Shard。这个拷贝过程需要一段时间,这段时间内只能由剩余主副本来承载流量,在恢复完成之前,整个系统会处于一个比较危险的状态,直到failover结束。

    这里就体现了副本(Replica)存在的一个理由,避免数据丢失,提高数据可靠性。副本(Replica)存在的另一个理由是读请求量很大的时候,一个Node无法承载所有流量,这个时候就需要一个副本来分流查询压力,目的就是扩展查询能力。


    角色部署方式

    接下来再看看角色分工的两种不同方式:

    在这里插入图片描述
    Elasticsearch支持上述两种方式

    1.混合部署(左图)

    • 默认方式。
    • 不考虑MasterNode的情况下,还有两种Node,Data Node和Transport Node,这种部署模式下,这两种不同类型Node角色都位于同一个Node中,相当于一个Node具备两种功能:Data和Transport。
    • 当有index或者query请求的时候,请求随机(自定义)发送给任何一个Node,这台Node中会持有一个全局的路由表,通过路由表选择合适的Node,将请求发送给这些Node,然后等所有请求都返回后,合并结果,然后返回给用户。一个Node分饰两种角色。
    • 好处就是使用极其简单,易上手,对推广系统有很大价值。最简单的场景下只需要启动一个Node,就能完成所有的功能。
    • 缺点就是多种类型的请求会相互影响,在大集群如果某一个Data Node出现热点,那么就会影响途经这个Data Node的所有其他跨Node请求。如果发生故障,故障影响面会变大很多。
    • Elasticsearch中每个Node都需要和其余的每一个Node都保持13个连接。这种情况下, - 每个Node都需要和其他所有Node保持连接,而一个系统的连接数是有上限的,这样连接数就会限制集群规模。
    • 还有就是不能支持集群的热更新。

    2.分层部署(右图)

    • 通过配置可以隔离开Node。
    • 设置部分Node为Transport Node,专门用来做请求转发和结果合并。
    • 其他Node可以设置为DataNode,专门用来处理数据。
    • 缺点是上手复杂,需要提前设置好Transport的数量,且数量和Data Node、流量等相关,否则要么资源闲置,要么机器被打爆。
    • 另外,还可以通过分组,使Transport Node只连接固定分组的DataNode,这样Elasticsearch的连接数问题就彻底解决了。
    • 可以支持热更新:先一台一台的升级DataNode,升级完成后再升级Transport Node,整个过程中,可以做到让用户无感知。

    ES数据层架构

    接下来我们看看当前Elasticsearch的数据层架构。


    数据存储

    Elasticsearch的Index和meta,目前支持存储在本地文件系统中,同时支持niofs,mmap,simplefs,smb等不同加载方式,性能最好的是直接将索引LOCK进内存的MMap方式。默认,Elasticsearch会自动选择加载方式,另外可以自己在配置文件中配置。这里有几个细节,具体可以看官方文档。

    索引和meta数据都存在本地,会带来一个问题:当某一台机器宕机或者磁盘损坏的时候,数据就丢失了。为了解决这个问题,可以使用Replica(副本)功能。


    副本(Replica)

    可以为每一个Index设置一个配置项:副本(Replicda)数,如果设置副本数为2,那么就会有3个Shard,其中一个是PrimaryShard,其余两个是ReplicaShard,这三个Shard会被Mater尽量调度到不同机器,甚至机架上,这三个Shard中的数据一样,提供同样的服务能力。

    副本(Replica)的目的有三个:

    • 保证服务可用性:当设置了多个Replica的时候,如果某一个Replica不可用的时候,那么请求流量可以继续发往其他Replica,服务可以很快恢复开始服务。
    • 保证数据可靠性:如果只有一个Primary,没有Replica,那么当Primary的机器磁盘损坏的时候,那么这个Node中所有Shard的数据会丢失,只能reindex了。
    • 提供更大的查询能力:当Shard提供的查询能力无法满足业务需求的时候, 可以继续加N个Replica,这样查询能力就能提高N倍,轻松增加系统的并发度。

    问题

    上面说了一些优势,这种架构同样在一些场景下会有些问题。Elasticsearch采用的是基于本地文件系统,使用Replica保证数据可靠性的技术架构,这种架构一定程度上可以满足大部分需求和场景,但是也存在一些遗憾:

    • Replica带来成本浪费。为了保证数据可靠性,必须使用Replica,但是当一个Shard就能满足处理能力的时候,另一个Shard的计算能力就会浪费。
    • Replica带来写性能和吞吐的下降。每次Index或者update的时候,需要先更新Primary Shard,更新成功后再并行去更新Replica,再加上长尾,写入性能会有不少的下降。
    • 当出现热点或者需要紧急扩容的时候动态增加Replica慢。新Shard的数据需要完全从其他Shard拷贝,拷贝时间较长。

    上面介绍了Elasticsearch数据层的架构,以及副本策略带来的优势和不足,下面简单介绍了几种不同形式的分布式数据系统架构。


    分布式系统

    第一种:基于本地文件系统的分布式系统

    在这里插入图片描述
    上图中是一个基于本地磁盘存储数据的分布式系统。Index一共有3个Shard,每个Shard除了Primary Shard外,还有一个Replica Shard。当Node 3机器宕机或磁盘损坏的时候,首先确认P3已经不可用,重新选举R3位Primary Shard,此Shard发生主备切换。然后重新找一台机器Node 7,在Node7 上重新启动P3的新Replica。由于数据都会存在本地磁盘,此时需要将Shard 3的数据从Node 6上拷贝到Node7上。如果有200G数据,千兆网络,拷贝完需要1600秒。如果没有replica,则这1600秒内这些Shard就不能服务。

    为了保证可靠性,就需要冗余Shard,会导致更多的物理资源消耗。

    这种思想的另外一种表现形式是使用双集群,集群级别做备份。

    在这种架构中,如果你的数据是在其他存储系统中生成的,比如HDFS/HBase,那么你还需要一个数据传输系统,将准备好的数据分发到相应的机器上。

    这种架构中为了保证可用性和可靠性,需要双集群或者Replica才能用于生产环境,优势和副作用在上面介绍Elasticsearch的时候已经介绍过了,这里就就不赘述了。

    Elasticsearch使用的就是这种架构方式。


    第二种:基于分布式文件系统的分布式系统(共享存储)

    在这里插入图片描述
    针对第一种架构中的问题,另一种思路是:存储和计算分离

    第一种思路的问题根源是数据量大,拷贝数据耗时多,那么有没有办法可以不拷贝数据?为了实现这个目的,一种思路是底层存储层使用共享存储,每个Shard只需要连接到一个分布式文件系统中的一个目录/文件即可,Shard中不含有数据,只含有计算部分。相当于每个Node中只负责计算部分,存储部分放在底层的另一个分布式文件系统中,比如HDFS。

    上图中,Node 1 连接到第一个文件;Node 2连接到第二个文件;Node3连接到第三个文件。当Node 3机器宕机后,只需要在Node 4机器上新建一个空的Shard,然后构造一个新连接,连接到底层分布式文件系统的第三个文件即可,创建连接的速度是很快的,总耗时会非常短。

    这种是一种典型的存储和计算分离的架构,优势有以下几个方面

    • 在这种架构下,资源可以更加弹性,当存储不够的时候只需要扩容存储系统的容量;当计算不够的时候,只需要扩容计算部分容量。
    • 存储和计算是独立管理的,资源管理粒度更小,管理更加精细化,浪费更少,结果就是总体成本可以更低。
    • 负载更加突出,抗热点能力更强。一般热点问题基本都出现在计算部分,对于存储和计算分离系统,计算部分由于没有绑定数据,可以实时的扩容、缩容和迁移,当出现热点的时候,可以第一时间将计算调度到新节点上。

    这种架构同时也有一个不足:访问分布式文件系统的性能可能不及访问本地文件系统。在上一代分布式文件系统中,这是一个比较明显的问题,但是目前使用了各种用户态协议栈后,这个差距已经越来越小了。HBase使用的就是这种架构方式。Solr也支持这种形式的架构。


    本文小结

    上述两种架构,各有优势和不足,对于某些架构中的不足或缺陷,思路不同,解决的方案也大相径庭,但是思路跨度越大,收益一般也越大。

    上面只是介绍了分布式数据(存储/搜索/分析等等)系统在存储层的两种不同架构方式,希望能对大家有用。但是分布式系统架构设计所涉及的内容广,细节多,权衡点众,如果大家对某些领域或者方面有兴趣,也可以留言,后面再探讨。

    展开全文
  • 分布式系统架构

    2021-11-09 17:25:29
    分布式系统知识体系大图 基础理论 SOA 到 MSA 的进化 SOA 面向服务架构 由于业务发展到一定程度后,需要对服务进行解耦,进而把一个单一的大系统按逻辑拆分成不同的子系统,通过服务接口来通讯。面向服务的...

    随着移动互联网的发展和智能终端的普及,计算机系统早就从单机独立工作过渡到多机器协作,集群按照分布式理论构建出庞大复杂的应用服务,在分布式的基础上正进行一场云原生的技术革命,彻底打破传统的开发方式,解放了新一代的生产力。

    分布式系统知识体系大图

    基础理论

    SOA 到 MSA 的进化

    SOA 面向服务架构

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

    MSA 微服务架构

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

    节点与网络

    节点

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

    网络

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

    • 同步网络

      • 节点同步执行
      • 消息延迟有限
      • 高效全局锁
    • 半同步网络

      • 锁范围放宽
    • 异步网络

      • 节点独立执行
      • 消息延迟无上限
      • 无全局锁
      • 部分算法不可行

    常用网络传输层有两大协议的特点简介:

    • TCP 协议

      • 首先 tcp 协议传输可靠,尽管其他的协议可以更快传输
      • tcp 解决重复和乱序问题
    • UDP 协议

      • 常量数据流
      • 丢包不致命

    时间与顺序

    时间

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

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

    • NTP 的一些缺点,无法完全满足分布式下并发任务的协调问题

      • 节点间时间不同步
      • 硬件时钟漂移
      • 线程可能休眠
      • 操作系统休眠
      • 硬件休眠

    • 逻辑时钟

      • 定义事件先来后到
      • t' = max(t, t_msg + 1)

    • 向量时钟

      • t_i' = max(t_i, t_msg_i)
    • 原子钟

    顺序

    有了衡量时间的工具,解决顺序问题自然就是水到渠成了。因为整个分布式的理论基础就是如何协商不同节点的一致性问题,而顺序则是一致性理论的基本概念,所以前文我们才需要花时间介绍衡量时间的刻度和工具。

    一致性理论

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

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

    强一致性 ACID

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

    • Atomicity:原子性,一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节;
    • Consistency:一致性,在事务开始之前和事务结束以后,数据库的完整性没有被破坏;
    • Isolation:隔离性,数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时,由于交叉执行而导致数据的不一致;
    • Durabilit:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

    分布式一致性 CAP

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

    • CAP:分布式计算系统不可能同时确保一致性(Consistency)、可用性(Availablity)和分区容忍性(Partition);
    • FLP:在异步环境中,如果节点间的网络延迟没有上限,只要有一个恶意的节点存在,就没有算法能在有限的时间内达成共识;
    • DLS:

      • 在一个部分同步网络的模型(也就是说:网络延时有界限但是我们并不知道在哪里)下运行的协议可以容忍 1/3 任意(换句话说,拜占庭)错误;
      • 在一个异步模型中的确定性的协议(没有网络延时上限)不能容错(不过这个论文没有提起随机化算法可以容忍 1/3 的错误);
      • 同步模型中的协议(网络延时可以保证小于已知 d 时间),可以令人吃惊的达到 100% 容错,虽然对 1/2 的节点出错可以发生的情况有所限制。

    弱一致性 BASE

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

    • 基本可用(Basically Available):基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用;
    • 软状态(Soft State):软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据至少会有三个副本,允许不同节点间副本同步的延时就是软状态的体现;
    • 最终一致性(Eventual Consistency):最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况。

    一致性算法

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

    首先我们要了解一致性的大前提原则 (CALM):
    CALM 原则的全称是 Consistency and Logical Monotonicity ,主要描述的是分布式系统中单调逻辑与一致性的关系,它的内容如下,参考 consistency as logical monotonicity

    • 在分布式系统中,单调的逻辑都能保证 “最终一致性”,这个过程中不需要依赖中心节点的调度;
    • 任意分布式系统,如果所有的非单调逻辑都有中心节点调度,那么这个分布式系统就可以实现最终“一致性”。

    然后再关注分布式系统的数据结构 CRDT(Conflict-Free Replicated Data Types):
    我们了解到分布式一些规律原则之后,就要着手考虑如何来实现解决方案,一致性算法的前提是数据结构,或者说一切算法的根基都是数据结构,设计良好的数据结构加上精妙的算法可以高效的解决现实的问题。经过前人不断的探索,我们得知分布式系统被广泛采用的数据结构 CRDT。
    参考《谈谈 CRDT》,A comprehensive study of Convergent and Commutative Replicated Data Types

    • 基于状态(state-based):即将各个节点之间的 CRDT 数据直接进行合并,所有节点都能最终合并到同一个状态,数据合并的顺序不会影响到最终的结果;
    • 基于操作(operation-based):将每一次对数据的操作通知给其他节点。只要节点知道了对数据的所有操作(收到操作的顺序可以是任意的),就能合并到同一个状态。

    了解数据结构后,我们需要来关注一下分布式系统的一些重要的协议HATs(Highly Available Transactions),ZAB(Zookeeper Atomic Broadcast):
    参考《高可用事务》《ZAB 协议分析》

    最后要学习的是业界主流的一致性算法 :
    说实话具体的算法我也还没完全搞懂,一致性算法是分布式系统最核心本质的内容,这部分的发展也会影响架构的革新,不同场景的应用也催生不同的算法。

    这一节我们说完分布式系统里面核心理论基础,如何达成不同节点之间的数据一致性,下面我们将会讲到目前都有哪些主流的分布式系统。

    场景分类

    文件系统

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

    • HDFS
    • FastDFS
    • Ceph
    • mooseFS

    数据库

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

    • 列式存储:Hbase
    • 文档存储:Elasticsearch,MongoDB
    • KV 类型:Redis
    • 关系型:Spanner

    计算

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

    • 离线:Hadoop
    • 实时:Spark
    • 流式:Storm,Flink/Blink

    缓存

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

    • 持久化:Redis
    • 非持久化:Memcache

    消息

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

    • Kafka
    • RabbitMQ
    • RocketMQ
    • ActiveMQ

    监控

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

    • Zookeeper

    应用

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

    • HSF
    • Dubbo

    日志

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

    • 日志采集:flume
    • 日志存储:ElasticSearch/Solr,SLS
    • 日志定位:Zipkin

    账本

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

    • 比特币
    • 以太坊

    设计模式

    上节我们列举了不同场景下不同分布式系统架构扮演的角色和实现的功能,本节我们更进一步归纳分布式系统设计的时候是如何考虑架构设计的、不同设计方案直接的区别和侧重点、不同场景需要选择合作设计模式,来减少试错的成本,设计分布式系统需要考虑以下的问题。

    可用性

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

    • 健康检查:系统实现全链路功能检查,外部工具定期通过公开端点访问系统
    • 负载均衡:使用队列起到削峰作用,作为请求和服务之间的缓冲区,以平滑间歇性的重负载
    • 节流:限制应用级别、租户或整个服务所消耗资源的范围

    数据管理

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

    • 缓存:根据需要将数据从数据存储层加载到缓存
    • CQRS(Command Query Responsibility Segregation): 命令查询职责分离
    • 事件溯源:仅使用追加方式记录域中完整的系列事件
    • 索引表:在经常查询引用的字段上创建索引
    • 物化视图:生成一个或多个数据预填充视图
    • 拆分:将数据拆分为水平的分区或分片

    设计与实现

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

    • 代理:反向代理
    • 适配器: 在现代应用程序和遗留系统之间实现适配器层
    • 前后端分离: 后端服务提供接口供前端应用程序调用
    • 计算资源整合:将多个相关任务或操作合并到一个计算单元中
    • 配置分离:将配置信息从应用程序部署包中移出到配置中心
    • 网关聚合:使用网关将多个单独的请求聚合到一个请求中
    • 网关卸载:将共享或专用服务功能卸载到网关代理
    • 网关路由:使用单个端点将请求路由到多个服务
    • 领导人选举:通过选择一个实例作为负责管理其他实例管理员,协调分布式系统的云
    • 管道和过滤器:将复杂的任务分解为一系列可以重复使用的单独组件
    • 边车:将应用的监控组件部署到单独的进程或容器中,以提供隔离和封装
    • 静态内容托管:将静态内容部署到 CDN,加速访问效率

    消息

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

    • 竞争消费者:多线程并发消费
    • 优先级队列: 消息队列分优先级,优先级高的先被消费

    管理与监控

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

    性能与扩展

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

    弹性

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

    • 隔离:将应用程序的元素隔离到池中,以便在其中一个失败时,其他元素将继续运行
    • 断路器:处理连接到远程服务或资源时可能需要不同时间修复的故障
    • 补偿交易:撤消一系列步骤执行的工作,这些步骤共同定义最终一致的操作
    • 健康检查:系统实现全链路功能检查,外部工具定期通过公开端点访问系统
    • 重试:通过透明地重试先前失败的操作,使应用程序在尝试连接到服务或网络资源时处理预期的临时故障

    安全

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

    • 联合身份:将身份验证委派给外部身份提供商
    • 看门人: 通过使用专用主机实例来保护应用程序和服务,该实例充当客户端与应用程序或服务之间的代理,验证和清理请求,并在它们之间传递请求和数据
    • 代客钥匙:使用为客户端提供对特定资源或服务的受限直接访问的令牌或密钥

    工程应用

    前文我们介绍了分布式系统的核心理论,面临的一些难题和解决问题的折中思路,罗列了现有主流分布式系统的分类,而且归纳了建设分布式系统的一些方法论,那么接下来我们将从工程角度来介绍真刀真枪搭建分布式系统包含的内容和步骤。

    资源调度

    巧妇难为无米之炊,我们一切的软件系统都是构建在硬件服务器的基础上。从最开始的物理机直接部署软件系统,到虚拟机的应用,最后到了资源上云容器化,硬件资源的使用也开始了集约化的管理。本节对比的是传统运维角色对应的职责范围,在 devops 环境下,开发运维一体化,我们要实现的也是资源的灵活高效使用。

    弹性伸缩

    过去软件系统随着用户量增加需要增加机器资源的话,传统的方式就是找运维申请机器,然后部署好软件服务接入集群,整个过程依赖的是运维人员的人肉经验,效率低下而且容易出错。微服务分布式则无需人肉增加物理机器,在容器化技术的支撑下,我们只需要申请云资源,然后执行容器脚本即可。

    • 应用扩容:用户激增需要对服务进行扩展,包括自动化扩容,峰值过后的自动缩容
    • 机器下线:对于过时应用,进行应用下线,云平台收回容器宿主资源
    • 机器置换:对于故障机器,可供置换容器宿主资源,服务自动启动,无缝切换

    网络管理

    有了计算资源后,另外最重要的就是网络资源了。在现有的云化背景下,我们几乎不会直接接触到物理的带宽资源,而是直接由云平台统一管理带宽资源。我们需要的是对网络资源的最大化应用和有效的管理。

    • 域名申请:应用申请配套域名资源的申请,多套域名映射规则的规范
    • 域名变更:域名变更统一平台管理
    • 负载管理:多机应用的访问策略设定
    • 安全外联:基础访问鉴权,拦截非法请求
    • 统一接入:提供统一接入的权限申请平台,提供统一的登录管理

    故障快照

    在系统故障的时候我们第一要务是系统恢复,同时保留案发现场也是非常重要的,资源调度平台则需要有统一的机制保存好故障现场。

    • 现场保留:内存分布,线程数等资源现象的保存,如 JavaDump 钩子接入
    • 调试接入:采用字节码技术无需入侵业务代码,可以供生产环境现场日志打点调试

    流量调度

    在我们建设好分布式系统后,最先受到考验的关口就是网关了,进而我们需要关注系统流量的情况,也就是如何对流量的管理,我们追求的是在系统可容纳的流量上限内,把资源留给最优质的流量使用、把非法恶意的流量挡在门外,这样节省成本的同时确保系统不会被冲击崩溃。

    负载均衡

    负载均衡是我们对服务如何消化流量的通用设计,通常分为物理层的底层协议分流的硬负载均衡和软件层的软负载。负载均衡解决方案已经是业界成熟的方案,我们通常会针对特定业务在不同环境进行优化,常用有如下的负载均衡解决方案

    • 交换机
    • F5
    • LVS/ALI-LVS
    • Nginx/Tengine
    • VIPServer/ConfigServer

    网关设计

    负载均衡首当其冲的就是网关,因为中心化集群流量最先打到的地方就是网关了,如果网关扛不住压力的话,那么整个系统将不可用。

    • 高性能:网关设计第一需要考虑的是高性能的流量转发,网关单节点通常能达到上百万的并发流量
    • 分布式:出于流量压力分担和灾备考虑,网关设计同样需要分布式
    • 业务筛选:网关同设计简单的规则,排除掉大部分的恶意流量

    流量管理

    • 请求校验:请求鉴权可以把多少非法请求拦截,清洗
    • 数据缓存:多数无状态的请求存在数据热点,所以采用 CDN 可以把相当大一部分的流量消费掉

    流控控制

    剩下的真实流量我们采用不同的算法来分流请求。

    • 流量分配

      • 计数器
      • 队列
      • 漏斗
      • 令牌桶
      • 动态流控
    • 流量限制在流量激增的时候,通常我们需要有限流措施来防止系统出现雪崩,那么就需要预估系统的流量上限,然后设定好上限数,但流量增加到一定阈值后,多出来的流量则不会进入系统,通过牺牲部分流量来保全系统的可用性。

      • 限流策略
      • QPS 粒度
      • 线程数粒度
      • RT 阈值
      • 限流工具 - Sentinel

    服务调度

    所谓打铁还需自身硬,流量做好了调度管理后,剩下的就是服务自身的健壮性了。分布式系统服务出现故障是常有的事情,甚至我们需要把故障本身当做是分布式服务的一部分。

    注册中心

    我们网络管理一节中介绍了网关,网关是流量的集散地,而注册中心则是服务的根据地。

    • 状态类型:第一好应用服务的状态,通过注册中心就可以检测服务是否可用
    • 生命周期:应用服务不同的状态组成了应用的生命周期

    版本管理

    • 集群版本:集群不用应用有自身对应的版本号,由不同服务组成的集群也需要定义大的版本号
    • 版本回滚:在部署异常的时候可以根据大的集群版本进行回滚管理

    服务编排

    服务编排的定义是:通过消息的交互序列来控制各个部分资源的交互。参与交互的资源都是对等的,没有集中的控制。微服务环境下服务众多我们需要有一个总的协调器来协议服务之间的依赖,调用关系,K8s 则是我们的不二选择。

    • K8s
    • Spring Cloud

      • HSF
      • ZK+Dubbo

    服务控制

    前面我们解决了网络的健壮性和效率问题,这节介绍的是如何使我们的服务更加健壮。

    • 发现资源管理那节我们介绍了从云平台申请了容器宿主资源后,通过自动化脚本就可以启动应用服务,启动后服务则需要发现注册中心,并且把自身的服务信息注册到服务网关,即是网关接入。注册中心则会监控服务的不同状态,做健康检查,把不可用的服务归类标记。

      • 网关接入
      • 健康检查
    • 降级:当用户激增的时候,我们首先是在流量端做手脚,也就是限流。当我们发现限流后系统响应变慢了,有可能导致更多的问题时,我们也需要对服务本身做一些操作。服务降级就是把当前不是很核心的功能关闭掉,或者不是很要紧的准确性放宽范围,事后再做一些人工补救。

      • 降低一致性约束
      • 关闭非核心服务
      • 简化功能
    • 熔断:当我们都做了以上的操作后,还是觉得不放心,那么就需要再进一步操心。熔断是对过载的一种自身保护,犹如我们开关跳闸一样。比如当我们服务不断对数据库进行查询的时候,如果业务问题造成查询问题,这是数据库本身需要熔断来保证不会被应用拖垮,并且访问友好的信息,告诉服务不要再盲目调用了。

      • 闭合状态
      • 半开状态
      • 断开状态
      • 熔断工具- Hystrix
    • 幂等:我们知道,一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。那么就需要对单次操作赋予一个全局的 id 来做标识,这样多次请求后我们可以判断来源于同个客户端,避免出现脏数据。

      • 全局一致性 ID
      • Snowflake

    数据调度

    数据存储最大的挑战就是数据冗余的管理,冗余多了效率变低而且占用资源,副本少了起不到灾备的作用,我们通常的做法是把有转态的请求,通过转态分离,转化为无状态请求。

    状态转移

    分离状态至全局存储,请求转换为无状态流量,比如我们通常会将登陆信息缓存至全局 redis 中间件,而不需要在多个应用中去冗余用户的登陆数据。

    分库分表

    数据横向扩展。

    分片分区

    多副本冗余。

    自动化运维

    我们从资源申请管理的时候就介绍到 devops 的趋势,真正做到开发运维一体化则需要不同的中间件来配合完成。

    配置中心

    全局配置中心按环境来区分,统一管理,减少了多处配置的混乱局面。

    • switch
    • diamend

    部署策略

    微服务分布式部署是家常便饭,如何让我们的服务更好地支撑业务发展,稳健的部署策略是我们首先需要考虑的,如下的部署策略适合不同业务和不同的阶段。

    • 停机部署
    • 滚动部署
    • 蓝绿部署
    • 灰度部署
    • A/B 测试

    作业调度

    任务调度是系统必不可少的一个环节,传统的方式是在 Linux 机器上配置 crond 定时任务或者直接在业务代码里面完成调度业务,现在则是成熟的中间件来代替。

    • SchedulerX
    • Spring 定时任务

    应用管理

    运维工作中很大一部分时间需要对应用进行重启,上下线操作,还有日志清理。

    • 应用重启
    • 应用下线
    • 日志清理

    容错处理

    既然我们知道分布式系统故障是家常便饭,那么应对故障的方案也是不可或缺的环节。通常我们有主动和被动的方式来处理:

    • 主动是在错误出现的时候,我们试图再试试几次,说不定就成功了,成功的话就可以避免了该次错误
    • 被动方式是错误的事情已经发生了,为了挽回,我们只是做时候处理,把负面影响降到最小

    重试设计

    重试设计的关键在于设计好重试的时间和次数,如果超过重试次数,或是一段时间,那么重试就没有意义了。开源的项目 spring-retry 可以很好地实现我们重试的计划。

    事务补偿

    事务补偿符合我们最终一致性的理念。补偿事务不一定会将系统中的数据返回到原始操作开始时其所处的状态。 相反,它补偿操作失败前由已成功完成的步骤所执行的工作。补偿事务中步骤的顺序不一定与原始操作中步骤的顺序完全相反。 例如,一个数据存储可能比另一个数据存储对不一致性更加敏感,因而补偿事务中撤销对此存储的更改的步骤应该会首先发生。对完成操作所需的每个资源采用短期的基于超时的锁并预先获取这些资源,这样有助于增加总体活动成功的可能性。 仅在获取所有资源后才应执行工作。 锁过期之前必须完成所有操作。

    全栈监控

    由于分布式系统是由众多机器共同协作的系统,而且网络也无法保证完全可用,所以我们需要建设一套对各个环节都能监控的系统,这样我们才能从底层到业务各个层面进行监控,出现意外的时候可以及时修复故障,避免更多的问题出现。

    基础层

    基础层面是对容器资源的监测,包含各个硬件指标的负载情况

    • CPU、IO、内存、线程、吞吐

    中间件

    分布式系统接入了大量的中间件平台,中间件本身的健康情况也需要监控。

    应用层

    • 性能监控:应用层面的需要对每个应用服务的实时指标(qps,rt),上下游依赖等进行监控
    • 业务监控:除了应用本身的监控程度,业务监控也是保证系统正常的一个环节,通过设计合理的业务规则,对异常的情况做报警设置

    监控链路

    • zipkin/eagleeye
    • sls
    • goc
    • Alimonitor

    故障恢复

    当故障已经发生后,我们第一个要做的就是马上消除故障,确保系统服务正常可用,这个时候通常做回滚操作。

    应用回滚

    应用回滚之前需要保存好故障现场,以便排查原因。

    基线回退

    应用服务回滚后,代码基线也需要 revert 到前一版本。

    版本回滚

    整体回滚需要服务编排,通过大版本号对集群进行回滚。

    性能调优

    性能优化是分布式系统的大专题,涉及的面非常广,这块简直可以单独拿出来做一个系列来讲,本节就先不展开。本身我们做服务治理的过程也是在性能的优化过程。
    参考《高并发编程知识体系》

    分布式锁

    缓存是解决性能问题的一大利器,理想情况下,每个请求不需要额外计算就立刻能获取到结果时最快。小到 CPU 的三级缓存,大到分布式缓存,缓存无处不在,分布式缓存需要解决的就是数据的一致性,这个时候我们引入了分布式锁的概念,如何处理分布式锁的问题将决定我们获取缓存数据的效率。

    高并发

    多线程编程模式提升了系统的吞吐量,但也同时带来了业务的复杂度。

    异步

    事件驱动的异步编程是一种新的编程模式,摒弃了多线程的复杂业务处理问题,同时能够提升系统的响应效率。

    总结

    最后总结一下,如果有可能的话,请尝试使用单节点方式而不是分布式系统。分布式系统伴随着一些失败的操作,为了处理灾难性故障,我们使用备份;为了提高可靠性,我们引入了冗余。

    分布式系统本质就是一堆机器的协同,而我们要做的就是搞出各种手段来然机器的运行达到预期。这么复杂的系统,需要了解各个环节、各个中间件的接入,是一个非常大的工程。庆幸的是,在微服务背景下,多数基础性的工作已经有人帮我们实现了。前文所描述的分布式架构,在工程实现了是需要用到分布式三件套 (Docker+K8S+Srping Cloud) 基本就可以构建出来了。

    分布式架构核心技术分布图如下:

    原图来源:https://dzone.com/articles/deploying-microservices-spring-cloud-vs-kubernetes

    分布式技术栈使用中间件:

    展开全文
  • 点击上方“朱小厮的博客”,选择“设为星标”后台回复"书",获取后台回复“k8s”,可领取k8s资料本文是学习大型分布式网站架构的技术总结。对架构一个高性能、高可用、可伸缩及...
  • 欢迎关注方志朋的博客,回复”666“获面试宝典图片来源:理想之城本文是学习大型分布式网站架构的技术总结。对架构一个高性能、高可用、可伸缩及可扩展的分布式网站进行了概要性描述,并给出一个架构...
  • 本文的目的之一即是挖掘出分布式系统架构设计的第一性原理,使其可以应用于千变万化的不同的技术领域。 架构是由人设计出来的,其与设计的人的架构理念强相关,欲彻底了解一个产品的架构必须要能量化它的设计理念,...
  • 美团外卖分布式系统架构设计

    千次阅读 2021-08-18 00:38:26
    背景美团外卖已经发展了五年,即时物流探索也经历了3年多的时间,业务从零孵化到初具规模,在整个过程中积累了一些分布式高并发系统的建设经验。最主要的收获包括两点:即时物流业务对故障和高延迟的容...
  • 即时物流系统阶段性的逐步实施分布式系统架构升级,最终解决了系统宕机的风险。 围绕成本、效率、体验核心三要素,即时物流体系大量结合AI技术,从定价、ETA、调度、运力规划、运力干预、补贴、核算、语音...
  • 现在的架构很多,各种各样的...那什么是分布式系统分布式系统是支持分布式处理的软件系统,是由通信网络互联的多处理机体系结构上执行任务的系统。包括分布式操作系统、分布式程序设计语言及其编译系统、分布式文...
  • - 前言 -本文是学习大型分布式网站架构的技术总结。对架构一个高性能、高可用、可伸缩及可扩展的分布式网站进行了概要性描述,并给出一个架构参考。文中一部分为读书笔记,一部分是个...
  • 作者介绍烂猪皮,十余年工作经验,曾在 Google 等外企工作过几年,精通 Java、分布式架构、微服务架构以及数据库,最近正在研究大数据以及区块链,希望能突破到更高的境界。本文是学习大型...
  • 一、大型分布式网站架构技术 1.1大型网站的特点 用户多,分布广泛 大流量,高并发 海量数据,服务高可用 安全环境恶劣,易受网络攻击 功能多,变更快,频繁发布 从小到大,渐进发展 ...
  • 本系列文章我把它命名为《分布式系统架构设计三十六式》,讲诉分布式系统里最重要的三十六个虚数的中观套路,而微服务的本质也是分布式,因此搞明白这三十六个最重要的知识点也就同时能搞明白微服务。 在前一篇...
  • 分布式系统架构简介

    2021-09-19 11:01:43
    最近几年,我们一直在谈论各式各样的架构,如高并发架构、异地多活架构、容器化架构、微服务架构、高可用架构、弹性化架构等。还有和这些架构相关的管理型的技术方法,如 DevOps、应用监控、自动化运维、SOA 服务...
  • 导读:随着互联网的不断发展,企业积累的数据越来越多。当单台数据库难以存储海量数据时,人们便开始探索如何将这些数据分散地存储到多台服务器的多台数据库中,逐渐形成了分布式数据库。如果将数据分散...
  • 【图文动画详解原理系列】9.分布式系统架构设计
  • 高可用HA(High Availability)是分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计减少系统不能提供服务的时间。 假设系统一直能够提供服务,我们说系统的可用性是100%。 如果系统每运行100个时间...
  • 本系列文章我把它命名为《分布式系统架构设计三十六式》,讲诉分布式系统里最重要的三十六个虚数的中观套路,而微服务的本质也是分布式,因此搞明白这三十六个最重要的知识点也就同时能搞明白微服务。 实现一个...
  • 第1章 面向服务的体系架构(SOA)1本章主要介绍和解决以下问题,这些也是全书的基础:HTTP协议的工作方式与HTTP网络协议栈的结构。如何实现基于HTTP协议和TCP协议的RPC调用,它们之间有何差别,分别适应何种场景。...
  • 本系列文章我把它命名为《分布式系统架构设计三十六式》,讲诉分布式系统里最重要的三十六个虚数的中观套路,而微服务的本质也是分布式,因此搞明白这三十六个最重要的知识点也就同时能搞明白微服务。 实现一个...
  • 高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求。 高并发相关常用的一些指标有响应时间(Response Time),吞吐量(Throughput...
  • 分布式系统类型多,涉及面非常广,不同类型的系统有不同的特点,批量计算和实时计算就差别非常大。这篇文章中,重点会讨论下分布式数据系统的设计,比如分布式存储系统,分布式搜索系统,分布式分析系统...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 305,537
精华内容 122,214
关键字:

分布式系统架构设计