[译] 论数据流的扩展性

在分布式系统中,数据流是一种简单但功能强大的储存和共享数据的机制。说数据流简单的缘由之一是由于它们很容易扩展。不管是从纵向(增长计算机的容量)仍是从横向(增长计算机的数量),数据流都能很好的扩展。本次数据流的扩展性的教程中,咱们将了解数据流纵向扩展性好的缘由,以及在横向扩展性上的选择。常见的问题是,当数据流在横向扩展时,对数据流的处理也可能要进行横向的扩展,这将会影响数据流处理管道的设计。html

纵向仍是横向扩展

为了不读者感到困惑,我这里先对于纵向和横向进行定义。纵向扩展是指你使用更强大的计算机来运行数据流的存储和处理程序。纵向扩展有时也称为向上扩展。你能够提升的包括磁盘的大小和速度、内存、CPU 的速度以及 CPU 的核心数量和显卡等设备。前端

Vertical scaling - AKA scaling up to a more powerful computer.

横向扩展指的是将工做分配给多台计算机。所以,数据流中的数据会在多台计算机之间分配,处理数据流的程序也会被分配 (至少它们能够被分配)横向扩展有时也称为向外扩展。你能够将一台计算机的工做横向扩展给多台计算机android

有两种状况下可能须要横向扩展:1、你得不到一个有更大内存和磁盘, 能够存储和处理你的全部数据的计算机。2、有这样的计算机,可是太贵买不起。ios

Horizontal scaling - AKA scaling out to multiple computers.

纵向扩展

上面已经提到了,纵向扩展意味着从配置低的计算机扩展到配置高的计算机。下面是传统计算机体系结构的各个层次:git

Computer architecture - vertical scaling.

数据离 CPU 越远,CPU 访问它的的速度就越慢。在上图中,数据离最底层越近,CPU 访问速度越慢。github

上述计算机体系结构的每一层都通过了优化,以便串行读取数据。这意味着,顺序读取位于磁盘上,RAM 或 L三、L二、L1 高速缓存中的数据比读取随机分布在磁盘、RAM 和高速缓存的数据要快。将数据顺序写入磁盘也要比随机写入磁盘各个部分要快得多。算法

数据流彻底是串行数据结构。它们连续地读取,连续地写入。这意味着,你能够在单台计算机上面轻松的向上扩展数据流。写入流的数据能够轻松的扩展到流文件中。向文件追加是写入文件的最快方式,相比之下,回到文件开始的位置并重写文件相对要慢。后端

从文件读取时,一大块数据被读入到 RAM。RAM 中的数据会被存入缓存,一小部分数据被读取并存入到 L3 缓存中,还有一小部分被读取并存入到 L2 缓存中,还有更小的一部分被读取并存入到 L1 缓存中,CPU 能够直接访问 L1 缓存并读取这部分数据。由于你的数据分散在整个磁盘中,若是你须要将一小块数据从磁盘读取到 CPU 中,你须要先读取一大块数据到 RAM中,而后再进入 L三、L2和L1高速缓存,那么在读取所需数据以前,这将会产生更屡次数的数据读取操做。当数据以串行方式位于一个大块中时,磁盘、RAM、L三、L2 和 L1 高速缓存读取数据的速度要比随机读取快得多。缘由很简单,由于读取次数少,每一次读取的块中都包含相关数据。缓存

由于数据流的读写很好地利用了现代计算机,当你扩展计算机运行数据流服务时,数据流服务的性能也会线性地增加。服务器

横向扩展

以前也已经提到了,横向扩展是将程序从一台计算机扩展到多台计算机。在数据流中,这意味着要将数据流中的消息分发到多台计算机。下面的图描述了将数据流的消息分发给多台计算机的过程:

The messages of a data stream distributed onto multiple computers.

将数据流的消息分发给多台计算机也称为对于数据流的分区

分区影响消息序列的顺序的一致性

对于数据流的分区会影响消息序列的顺序的一致性。在一台计算机上,数据流的消息的读取和写入的顺序能够保证是相同的。一旦你对数据流进行了分区,咱们就不能保证这个顺序了。具体的分区方法决定了会以何种方式影响消息序列的顺序。

Round Robin 分区

Round Robin 分区是跨多台计算机对数据流的消息进行分区的最简单的方法。Round Robin 分区只是在计算机之间均匀和顺序地分发消息。换句话说,1 号消息存储在 1 号计算机上,2 号消息存储在 2 号计算机上,以此类推。当全部的计算机都接收到消息后,Round Robin 分区的方法再从 1 号计算机开始。

若是只有一个应用程序写入数据流,使用 Round Robin 分区的方法是最简单的。可是要是有多个程序同时运行就很差办了。

当使用 Round Robin 分区机制时,对于流的读取来讲,按照流中划分消息以前的顺序从新组装流中的消息是至关容易的。输出流只需以轮询调度方式从每个分区读取一条消息。

基于字段值分区

基于字段值分区的原理是经过每一个消息的特定值将消息分发给不一样的计算机。一般,识别ID(例如主键值)做为分发消息的字段。计算每一个字段值的哈希值,而后利用这个哈希值将消息映射到集群的一台计算机中。

当使用字段值分区时,极可能会丢失整个消息序列的顺序。写入同一台计算机(同一分区)的消息仍保持相互之间的顺序,可是整个序列的顺序可能会丢失,由于其余的计算机(其余分区)可能在它们以前被读取。下图就说明了这个问题:

Key based data stream partitioning may affect overall message sequence.

若是要得到数据流分区的所有好处,就不能控制流处理器从不一样分区读取数据的顺序。若是你还想扩展流处理器,那更不切实际。下图就说明这个问题:

Key based data stream partitioning with stream processor partitioning too, will most likely affect overall message sequence.

在不少状况下,其实你并不须要完整的消息序列的顺序。你须要的多是在数据流中相关消息的消息序列顺序。例如,若是消息表示对于客户端更新,那么将对于同一客户端的更新消息应该集中在集群中的同一台计算机(同一个分区)上。这样,你就能够保证对于每个客户的更新顺序,这对于你的程序来讲已经足够了。对于不一样客户端更新顺序可能改变,可是对于同一逻辑实体(客户端)的更新序列保持相同,对于不一样逻辑实体的更新之间的序列的改变可能不必定是个问题。

对于消息进行分区以便最后全部的相关消息都会在同一台服务器上,这一般是经过对消息主键上的数据进行分区完成的。这样应该会保证同一逻辑实体(例如客户端)的全部相关消息都会存储在同一台计算机上。

基于字段值的分区,消息的分布可能会不均匀。它取决于字段的分布以及将消息映射到群集计算机的哈希函数。不合适的哈希算法可能会将更多消息映射到某些计算机上而不是其余计算机。这样不均匀的消息分发会致使集群计算机之间负载分布的不平均,这又会致使对于计算机资源的非最佳利用。

在某些状况下,基于非标识字段值(例如外键或某些其余字段值)对消息进行分区是有意义的。这显然会致使消息离散分布,甚至可能致使很是不均匀的分布,例如使用一个比其余值更广泛的值做为分区值。

下面是横向扩展数据流的示意图,其中集群中的计算机的消息分布不必定均匀:

Key based data stream partitioning may lead to uneven distribution of the messages in the stream across the computers in the cluster.

若是发现译文存在错误或其余须要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可得到相应奖励积分。文章开头的 本文永久连接 即为本文在 GitHub 上的 MarkDown 连接。


掘金翻译计划 是一个翻译优质互联网技术文章的社区,文章来源为 掘金 上的英文分享文章。内容覆盖 AndroidiOS前端后端区块链产品设计人工智能等领域,想要查看更多优质译文请持续关注 掘金翻译计划官方微博知乎专栏

相关文章
相关标签/搜索