分布式系统种类繁多,涉及面广。不同类型的系统有不同的特点,批计算和实时计算有很大区别。图片来自Pexels。本文将重点介绍分布式数据系统的设计,例如分布式存储系统、分布式搜索系统、分布式分析系统。我们简单看一下Elasticsearch的架构。Elasticsearch集群架构Elasticsearch是一个非常著名的开源搜索和分析系统,广泛应用于互联网的各个领域。尤其是以下三个方面尤为突出:在搜索方面,与Solr相比,它是名副其实的后起之秀,成为众多搜索系统的最佳选择。与MongoDB相比,Json文档数据库具有更好的读写性能,支持更丰富的地理位置查询和数文混合查询。时序数据分析与处理,目前在日志处理、监控数据存储、分析与可视化方面做得很好,可以说是该领域的佼佼者。Elasticsearch的详细介绍可以到官网查看。我们先来看看Elasticsearch中的几个关键概念:节点(Node):物理概念,一个运行中的Elasticsearch实例一般是一台机器上的一个进程。索引(Index):逻辑概念,包括配置信息映射和反向向前数据文件。一个索引数据文件可以分布在一台机器上,也可以分布在多台机器上。另一层索引是倒排索引文件。Shard:为了支持更大的数据量,索引一般会按照一定的维度分成多个部分。每个部分都是一个分片,分片由一个节点管理。一个节点(Node)一般管理着多个分片。这些分片可能属于同一个索引,也可能属于不同的索引。但是为了可靠性和可用性,同一个索引的分片应该尽可能分布在不同的节点(Node)上。)优越的。有两种类型的分片,主分片和副本分片。Replica:同一个shard的备份数据。一个分片可能有0个或多个副本。这些副本中的数据保证是强一致或最终一致的。如上图所示,可以用图形表示如下:Index1:蓝色部分,有3个Shard,分别是P1、P2、P3,分别位于3个不同的Node,这里没有Replica。Index2:绿色部分,有2个Shard,分别是P1和P2,分别位于2个不同的Node。而每个Shard都有一个Replica,即R1和R2。基于系统可用性的考虑,同一个Shard的Primary和Replica不能位于同一个Node。这里Shard1的P1和R1分别位于Node3和Node2。如果某个时刻Node2宕机了,服务基本不会受到影响,因为还有一个P1和R2仍然可用。因为是主备架构,当主分片失效时,需要进行切换。这时候需要选举一个replica作为新的primary。除了消耗一点时间外,还有数据丢失的风险。索引流程在建立索引(Index)时,首先通过路由规则将一个Doc定位到主分片,并将该Doc发送到主分片建立索引。索引成功后才返回success。在该架构中,所有索引数据都存储在分片中,主分片和副本分片各存储一份。当一个副本分片或主分片丢失时(如机器宕机、网络中断等),丢失的分片需要在其他节点中恢复。这个时候就需要把这个shard的所有数据从其他副本(Replica)上复制到新的Node上来构造一个新的shard。这个复制过程需要一段时间。在此期间,只有剩余的主副本可以承载流量。在恢复完成之前,整个系统会处于比较危险的状态,直到Failover结束。这里有一个副本(Replica)存在的原因,避免数据丢失,提高数据可靠性。副本存在的另一个原因是,当有大量的读请求时,一个Node无法承载所有的流量。这时候就需要一个副本来分担查询压力,目的是扩展查询能力。角色部署方式接下来我们看一下两种不同的角色划分方式:Elasticsearch支持以上两种方式:混合部署分层部署混合部署(如左图):默认方式。不考虑MasterNode,有两种Node,DataNode和TransportNode。在这种部署模式下,这两种不同类型的Node角色位于同一个Node中,相当于一个Node有两个功能:Data和Transport。当有Index或Query请求时,该请求被随机(自定义)发送到任何Node。这个Node会持有一个全局路由表,通过路由表选择合适的Node,将请求发送给这些Node,然后等待所有请求返回,合并结果,再返回给用户。一个节点扮演两个角色。优点是使用极其简单,容易上手,对系统推广有很大的价值。在最简单的场景下,只需要启动一个Node就可以完成所有的功能。缺点是多种类型的请求会相互影响。在大型集群中,如果一个数据节点存在热点,就会影响所有其他经过该数据节点的跨节点请求。如果发生故障,故障的影响将变得更大。Elasticsearch中的每个节点都需要与其他每个节点保持13个连接。在这种情况下,每个Node都需要与所有其他Node保持连接,而一个系统中的连接数是有上限的,因此连接数会限制集群的大小。另外不能支持集群的热更新。分层部署(如右图):节点可以通过配置进行隔离。设置一些Nodes作为TransportNodes,专门用于请求转发和结果合并。其他的Nodes可以设置为DataNodes,专门用来处理数据。缺点是上手比较复杂,需要提前设置Transport的个数,这个个数和DataNode、流量等相关,否则会造成资源闲置或者炸机.优点是角色相互独立,不会互相影响。一般TransportNode的流量分布比较均匀,很少会出现单机CPU或流量被充分利用的情况。但由于DataNode处理数据,很容易被单机资源占满,如CPU、网络、磁盘等,独立后,如果一个DataNode发生故障,只会影响单个节点的数据处理,并且不会影响其他节点的请求,并且将影响限制在最小。角色独立后,只需要TransportNode连接所有DataNode,DataNode不需要连接其他DataNode。集群中DataNode的数量远大于TransportNode的数量,因此集群的规模可以更大。另外,还可以通过分组让TransportNode只连接固定组的DataNode,这样就彻底解决了Elasticsearch的连接数问题。可以支持热更新:先对DataNode进行一个一个的升级,升级完成后再对TransportNode进行升级。在整个过程中,用户可能会失去知觉。以上介绍了Elasticsearch的部署层架构。不同的部署方式适用于不同的场景,需要根据自己的需要选择合适的方式。Elasticsearch数据层架构接下来我们看一下目前Elasticsearch数据层架构。数据存储Elasticsearch的Index和Meta目前支持存储在本地文件系统中,支持niofs、mmap、simplefs、smb等不同的加载方式。性能最好的是直接将索引锁入内存的mmap方法。Elasticsearch默认会自动选择加载方式,你可以自己在配置文件中配置。这里有一些细节,具体见官方文档。索引和元数据都存储在本地,这会导致一个问题:当某台机器宕机或磁盘损坏时,数据会丢失。要解决这个问题,可以使用Replica(复制)功能。副本(Replica)可以为每个Index设置一个配置项:副本(Replica)的数量。如果副本数设置为2,那么就会有3个分片,其中一个是primaryshard,另外两个是replicashard。这三个分片会被Mater尽可能的分派到不同的机器甚至机架上。这三个分片中的数据是相同的,提供相同的服务能力。Replica(副本)有三个目的:保证服务可用性:当设置了多个Replica时,如果某个Replica不可用,请求流量可以继续发送给其他Replica,可以快速恢复服务。保证数据可靠性:如果只有一个Primary,没有Replica,那么当主机磁盘损坏时,本Node所有Shard的数据都会丢失,只能重新索引。提供更大的查询能力:当Shard提供的查询能力不能满足业务需求时,可以继续增加N个Replicas,这样查询能力可以提升N倍,轻松提升系统的并发量。有上面问题中提到的一些优点,但是这种架构在某些场景下也存在一些问题。Elasticsearch采用基于本地文件系统的技术架构,使用Replica来保证数据的可靠性。这种架构在一定程度上可以满足大部分需求和场景。但也有一些遗憾:Replica带来了成本的浪费。为了保证数据的可靠性,必须使用Replica,但是当一个Shard能够满足处理能力时,另一个Shard的计算能力就会被浪费。Replica带来写入性能和吞吐量的下降。每次进行Index或Update时,需要先更新PrimaryShard,更新成功后再并行更新Replica。再加上长尾,写性能会下降很多。出现热点或急需扩容时,动态增加Replicas速度较慢。新分片的数据需要从其他分片中完整复制过来,复制时间较长。以上介绍了Elasticsearch数据层的架构,以及副本策略带来的优缺点。下面简单介绍几种不同形式的分布式数据系统架构。分布式系统基于本地文件系统的分布式系统上图是一个基于本地磁盘存储数据的分布式系统。Index一共有3个shard,每个shard除了primaryshard还有一个replicashard。当Node3机器宕机或者磁盘损坏时,首先确认P3不可用,然后重新选举R3作为PrimaryShard,这个shard就会从active切换到standby。然后再找一台机器Node7,在Node7上重启P3的新Replica。由于数据会存储到本地磁盘,所以此时需要将Shard3的数据从Node6复制到Node7。如果有200G数据,千兆网络,复制需要1600秒。如果没有Replica,这些分片在1600秒内无法服务。为了保证可靠性,需要冗余的分片,这会导致更多的物理资源消耗。这种思想的另一种体现是使用双集群进行集群级别的备份。在这种架构下,如果你的数据是在其他存储系统中产生的,比如HDFS/HBase,那么你还需要一个数据传输系统,将准备好的数据分发到相应的机器上。为了保证该架构的可用性和可靠性,需要在生产环境中使用双集群或Replicas。优点和副作用在上面介绍Elasticsearch的时候已经介绍过了,这里不再赘述。Elasticsearch使用这种架构方法。基于分布式文件系统的分布式系统解决了第一种架构中的问题,另一种思路是:存储和计算分离。第一个思路的问题根源在于数据量大,复制数据耗时长。有什么办法不复制数据吗?要实现这一点,一种思路是底层存储层使用共享存储,每个分片只需要连接到分布式文件系统中的一个目录/文件就够了,分片不包含数据,只包含计算部分。相当于每个Node只负责计算部分,存储部分放在底层的另一个分布式文件系统,比如HDFS。在上图中,节点1连接到第一个文件;节点2连接到第二个文件;节点3连接到第三个文件。当Node3机器宕机时,只需要在Node4机器上创建一个空的分片,然后构造一个新的连接来连接底层分布式文件系统中的第三个文件。创建连接的速度非常快,总时间会很短。这是典型的存储和计算分离的架构。它有以下优点:在这种架构下,资源可以更加灵活。当存储不够时,只需要扩展存储系统的容量;当计算量不够时,只需要扩展部分容量。存储和计算独立管理,资源管理粒度更小,管理更精细,浪费更少,综合成本更低。负载更突出,抗热点能力更强。一般热点问题基本都出现在计算部分。对于存储和计算分离系统,计算部分可以实时扩展、收缩和迁移,因为没有绑定数据。在节点上。这种架构也有一个缺点:访问分布式文件系统的性能可能不如访问本地文件系统。在上一代的分布式文件系统中,这是一个比较明显的问题,但是在使用了各种用户态协议栈之后,差距已经越来越小了。HBase就是采用这种架构方式,Solr也支持这种架构形式。综上所述,以上两种架构各有优缺点。对于一些架构的缺点或者缺陷,思路不同,解决的办法也大不相同,但是思路的跨度越大,好处就越大。以上仅介绍了存储层分布式数据(存储/搜索/分析等)系统的两种不同架构,希望对大家有所帮助。但是,分布式系统架构设计涉及的内容和细节非常广泛,需要权衡取舍。如果你对某些领域或方面感兴趣,也可以留言,稍后再讨论。
