从数据库到消息系统,大多数分布式系统采用了数据处理和数据存储共存于同一节点的方法。 这种设计由于减少了网络上的数据传输,可以提供更简单的基础架构和某些场景下的性能优势,但代价是牺牲了系统的可扩展性和高可用性。
Pulsar采用了一种截然不同的存储和计算分离的系统架构,这种架构近年开始出现在许多“云原生”解决方案中。这其中的一部分原因在于近年来网络性能的显着改进。
Pulsar的架构中数据服务和数据存储是单独的两层:数据服务层由无状态的“Broker”节点组成,而数据存储层则由“Bookie”节点组成。
Figure 1. 传统架构 vs. 存储计算分层架构
这种存储和计算分离的架构给Pulsar带来了很多优势。
首先,在Pulsar这种分层架构中,服务层和存储层都能够独立扩展,可以提供灵活的弹性扩容。特别是在弹性环境(例如云和容器)中能够自动扩容缩容,并动态适应流量的峰值。
而且Pulsar这种分层架构显著降低了集群扩展和升级的复杂性,提高了系统可用性和可管理性。
此外,这种设计对容器是非常友好的,这使Pulsar成为流原生平台的理想选择。
Pulsar系统架构的优势也包括Pulsar的分片存储数据的方式。正如我们在
Pulsar以分片为中心的架构中详细描述的那样,Pulsar将主题分区按照更小的分片粒度来存储,然后将这些分片均匀打散分布在存储层的“bookie”节点上。这种以分片为中心的数据存储方式,将主题分区作为一个逻辑概念,分为多个较小的分片,并均匀分布和存储在存储层中。它为Pulsar带来了更好的性能,更灵活的扩展性和更高的可用性。
接下来,让我们结合数据处理中的各种不同的IO访问模式,来深入了解Pulsar的系统架构的优势。
IO访问模式的优势
流系统中通常有三种IO访问模式:
1.写(Writes):将新数据写入系统中;
2.追尾读(Tailing Reads):读取最近写入的数据;
3.追赶读(Catch-up Reads):读取历史的数据,例如当一个新消费者想要从较老的时间点开始访问数据,或者当老的消费者在长时间离线后又得到恢复时。
和大多数其他消息系统不同,在Pulsar中,这些IO访问模式中的每一种都与其他模式隔离。我将对比在同样IO访问模式下, Pulsar和其他的传统消息系统(存储和服务绑定在单个节点上,如Apache Kafka)的不同。
在传统消息系统(下图2中的左侧图)中,每个Broker只能利用本地磁盘提供的存储容量,这会给系统带来一些限制:
1.Broker可以存储和服务的数据量受限于单个节点的存储容量。 因此,一旦Broker节点的存储容量耗尽,它就不能再提供写请求,除非在写入之前首先清除现有的部分数据。
2.对于单个分区如果需要存储多个备份在多个节点中,容量最小的节点将决定分区的最终大小。
Figure 2. 传统架构 vs. 存储计算分层架构
相比之下,在Apache Pulsar(上图2中的右侧图)中,数据服务和数据存储是分离的,Pulsar服务层的任意Broker都可以访问存储层的所有存储节点,并利用所有节点的整体存储容量。
在服务层,从系统可用性的角度来看,这也有着深远的影响,只要有任意一个Pulsar的Broker还在运行,用户就可以通过这个Broker读取先前存储在集群中的任何数据,并且还能够继续写入数据。
现在让我们更详细地看一下每种IO模式。
写
在传统消息系统架构中,一个分区的所有权会分配给Leader Broker。 对于写请求,该Leader Broker接受写入并将数据复制到其他Broker。 如下面图3左侧所示,数据首先写入Leader Broker并复制给其他followers。 数据的一次持久化写入的过程需要两次网络往返。
在Pulsar的系统架构中,数据服务由无状态Broker完成,而数据存储在持久存储中。 数据将会发送给服务于该分区的Broker,该Broker并行写入数据到存储层的多个节点中。 一旦存储层成功写入数据并确认写入,Broker会将数据缓存在本地内存中以提供追尾读(Tailing Reads)(我们将在下一段中讨论)。
Figure 3. Writes模式对比
如图3所示,相比于传统的系统架构,Pulsar的系统架构并不会在写入的IO路径上引入额外的网络往返或带宽开销,但是,由于存储和服务分离,显著提高了系统的灵活性和可用性。
追尾读
对于读取最近写入的数据这种场景,在传统消息系统架构中,消费者从Leader Broker的本地存储中读取数据;在Pulsar的分层架构中,消费者从Broker就可以读取数据,由于Broker已经将数据缓存在内存中,并不需要去访问存储层。
Figure 4. Tailing Reads模式对比
在这两种架构下,只需要一次网络往返就可以读取到数据。但是,由于Pulsar在系统中自己管理缓存中的数据,没有依赖于文件系统缓存,这样Tailing Reads很容易在缓存中命中,而无需从磁盘读取。传统的系统架构一般依赖于文件系统的缓存,读写操作不仅会相互竞争资源(包括内存),还会与代理上发生的其他处理任务竞争,很容易造成pagecache中缓存的替换,造成对磁盘的访问。
追赶读
看一下追赶读(Catch-up Reads)会更有趣。 在传统的系统架构中,对Tailing reads和Catch-up reads两种访问模式进行了同样的处理。即使一份数据被存在多个Broker中,所有的Catch-up reads仍然只能发送给Leader Broker。
在Pulsar的分层架构中,历史(旧)数据存储在存储层中。 Catch-up读可以通过存储层来并行读取数据,而不会与Write和Tailing Reads两种IO模式竞争或干扰。
三种IO模式放在一起看我们上面讨论了Pulsar的分层架构如何为不同类型的工作负载提供高性能和可扩展性。但是Pulsar的分层架构带来的好处,远远不止这些。以下是Pulsar能够胜任消息系统之外的一些方面。
存储无限大小的流
存储和计算分离的系统架构,让Pulsar可以被用作流数据平台。 这样用户和应用程序可以使用Pulsar并行访问流式计算中的最新数据和批量计算中的历史数据。
由于Pulsar基于分片的架构,Pulsar的一个主题在理论上可以达到无限大小。当容量不足时,用户只需要添加容器或存储节点即可轻松扩展存储层,而无需重新平衡数据;新添加的存储节点会被立即用于新的分片或者分片副本的存储。
因此,Pulsar不仅可以存储当前数据,还可以存储完整的历史数据。
数据查询和数据分析
对数据流整个历史记录的存储能力,使用户可以在其数据上运行各种数据分析工具。 Pulsar与Presto的集成就是一个很好的例子,如下所示。 Pulsar SQL许Presto SQL引擎直接访问存储层中的数据,从而实现交互式SQL查询数据,而不会干扰Pulsar的其他工作负载。
Figure 6. Presto integration with Apache Pulsar
Pulsar还可以与其他数据处理引擎进行类似集成,来作为批流一体的数据存储平台,例如Apache Spark或Apache Flink,这进一步扩展了Pulsar消息系统之外的角色。
如果您想要了解更多Pulsar的分层分片的系统架构,欢迎通过以下方式关注Apache Pulsar:
来源: weixin
作者: ApachePulsar
原文链接: Apache Pulsar:灵活的可扩展的批流一体的系统架构