全面介绍分布式系统
什么是分布式系统?为什么这么复杂?
Introduction
随着世界不断增长的技术扩张,分布式系统变得越来越普遍。他们是计算机科学领域的一个庞大而复杂的领域。
本文旨在以基本方式向您介绍分布式系统,向您展示此类系统的不同类别,同时不深入细节。
What is a distributed system?
最简单定义的分布式系统是一组计算机一起工作,以最终用户身份显示为一台计算机。
这些机器有一个共享的状态,可以并发地操作,并且可以独立地失败,而不会影响整个系统的正常运行时间。
我建议我们通过分配系统的例子逐步完成工作,以便更好地理解这一切:
让我们从数据库开始!传统的数据库存储在一台机器的文件系统中,每当你想要获取/插入信息时,你就直接与它对话。
对于我们分发这个数据库系统,我们需要同时在多台机器上运行这个数据库。用户必须能够与他选择的任何机器进行对话,并且不应该能够告诉他,他没有与一台机器对话——如果他将一个记录插入到节点#1中,那么节点#3必须能够返回该记录。
Why distribute a system?
系统总是按需要分配的。问题的真相是——管理分布式系统是一个复杂的主题,充满陷阱和地雷。部署、维护和调试分布式系统是一件令人头痛的事情,所以为什么要去那里呢?
分布式系统使您能够水平地伸缩。回到我们之前的单一数据库服务器示例,处理更多流量的惟一方法是升级数据库正在运行的硬件。这就是垂直伸缩。
尽管可以垂直伸缩,但是在某个点之后,您会发现即使是最好的硬件也不足以提供足够的流量,更不用说主机不切实际了。
横向伸缩意味着添加更多的计算机,而不是升级单个硬件。
在一定的阈值之后,它比垂直扩展要便宜得多,但这不是偏好的主要情况。
垂直扩展只会将性能提升到最新硬件的性能。这些能力对于中等到大工作量的技术公司来说是不够的。
水平扩展最好的一点是,你没有限制你可以伸缩的程度——每当性能降低时,你只需添加另一台机器,就有可能达到无穷大。
轻松扩展并不是从分布式系统获得的唯一好处。容错和低延迟也同样重要。
容错(Fault Tolerance) - 跨越两个数据中心的十台机器集群本质上比单台机器更容错。即使一个数据中心着火,您的应用程序仍然可以工作。
低延迟(Low Latency)——网络数据包在世界范围内传播的时间物理上受到光速的限制。例如,在纽约至悉尼之间的光纤电缆中,请求往返时间(即来回)的最短时间是160ms。分布式系统允许您在两个城市中都有一个节点,允许流量到达最接近它的节点。
但是,对于一个分布式系统来说,你需要在这些机器上运行的软件,专门设计用于同时在多台计算机上运行,并处理随之而来的问题。这并非易事。
Scaling our database
假设我们的web应用程序变得疯狂流行。想象一下,我们的数据库每秒的查询量是它能够处理的两倍。您的应用程序将立即开始降低性能,这将引起您的用户的注意。
让我们一起工作,并使我们的数据库规模满足我们的高要求。
有一种方法可以提高读取性能,即通过所谓的主从复制策略。在这里,您创建了两个与主要服务器同步的新数据库服务器。问题是你只能从这些新的实例中读取。
无论何时插入或修改信息,都要与主数据库对话。反过来,它异步地通知了变更的奴隶,并将其保存起来。
恭喜,您现在可以执行3倍的读取查询!这不是很好吗?
疑难杂症!我们立即失去了关系数据库的ACID保证中的C,它代表一致性。
你看,现在有一种可能性,我们在数据库中插入一条新的记录,然后立即发出一个读取查询并获取任何东西,就好像它不存在一样!
从主向从传播新信息不是瞬间发生的。实际上存在一个时间窗口,其中可以获取陈旧的信息。如果不是这样,那么您的写性能就会受到影响,因为它必须同步等待要传播的数据。
分布式系统带来了一些折衷。如果你想充分扩展,这个特殊的问题是你必须忍受的。
Continuing to Scale
使用从数据库方法,我们可以在一定程度上横向扩展读取流量。这很棒,但我们在写入流量方面遇到了一堵墙 - 它仍然在一台服务器上。
我们在这里没有太多选择。我们只需要将我们的写入流量分割为多个服务器,因为无法处理它。
一种方法是使用多主复制策略。在那里,您没有只能读取的从数据库,而是有多个主节点,这些主节点支持读写。不幸的是,由于您现在有了创建冲突的能力(e),这就变得非常复杂。插入两个相同ID的记录。
让我们继续使用另一种称为分片(sharding)的技术(也称为分区)。
通过分片,您将服务器分割成多个更小的服务器,称为碎片。这些碎片都持有不同的记录——您创建的规则是什么样的记录进入哪个碎片。创建这样的规则是非常重要的,这样数据才能以统一的方式传播。
对此的一种可能的方法是根据关于记录的某些信息(例如具有名称A-D的用户)来定义范围。
应该非常小心地选择这个切分键,因为负载并不总是基于任意列。(e。更多的人是以C而不是Z来命名的。一个单一的shard接收到的请求多于其他的被称为热点,必须避免。一旦拆分,重新分片数据变得异常昂贵,并可能导致严重的停机,就像FourSquare臭名昭著的11小时停机一样。
为了保持我们的例子简单,假设我们的客户端(Rails应用程序)知道每个记录使用哪个数据库。值得注意的是,有许多分片策略,这是一个简单的例子来说明这个概念。
我们现在赢得了很多 - 我们可以将写入流量增加N倍,其中N是碎片的数量。这实际上给我们几乎没有限制 - 想象我们可以通过这种分区获得多么细微的粒度。
Pitfall(陷阱)
软件工程中的一切或多或少都是一种折衷,这也不例外。 Sharding不是简单的壮举,而是最好避免直到真正需要。
现在我们通过分区键之外的键进行查询的效率非常低(他们需要遍历所有的分片)。 SQL JOIN查询更加糟糕,而且复杂的查询实际上无法使用。
Decentralized vs Distributed
在我们进一步讨论之前,我想区分这两个术语。
尽管这些词听起来很相似,可以得出结论意味着它们在逻辑上相同,但它们的差异会产生重大的技术和政治影响。
在技术层面上,分散型仍然是分布式的,但是整个分散式系统并不属于一个行动者。没有一个公司可以拥有分散的系统,否则它不会再分散。
这意味着我们今天将要发布的大多数系统都可以被看作是分布式集中式系统 - 这就是他们所做的。
如果你仔细想一想 - 创建一个分散系统就比较困难,因为那时你需要处理一些参与者是恶意的情况。正常分布式系统并非如此,因为您知道您拥有所有节点。
注意:这个定义已经讨论了很多,并且可能与其他的(对等的,联合的)混淆。在早期的文献中,它的定义也不同。无论如何,我给你的定义是,我觉得现在最广泛使用的是区块链和加密货币普及了这个术语。
Distributed System Categories
现在,我们将讨论几个分布式系统类别,并列出它们最大的公开产品使用情况。记住,大多数这样的数字都是过时的,而且在你阅读这篇文章的时候,它们可能会更大。
Distributed Data Stores
分布式数据存储是最广泛使用和公认的分布式数据库。大多数分布式数据库都是NoSQL非关系数据库,仅限于键值语义。它们以一致性或可用性的代价提供难以置信的性能和可伸缩性。
已知的规模 - 早在2015年,苹果就已知使用75,000个Apache Cassandra节点存储超过10PB的数据.
没有首先引入CAP定理,我们就不能讨论分布式数据存储。
CAP Theorem
CAP定理早在2002年就证明,分布式数据存储不能同时具有一致性,可用性和分区容错性。
一些快速定义:
- 一致性 - 您按顺序读取和写入的内容是预期的。
- 可用性 - 整个系统不会死亡 - 每个非故障节点总是返回一个响应。
- 分区容忍 尽管存在网络分区,系统仍会继续运行并保持其一致性/可用性保证
实际上,对于任何分布式数据存储,分区容限必须是给定的。正如许多地方所提到的,其中的一篇文章,如果没有分区容差,就无法保证一致性和可用性。
想一想:如果你有两个节点接受信息并且他们的连接中断 - 它们将如何可用并同时为你提供一致性?他们无法知道其他节点正在做什么,因此可能变为脱机(不可用)或使用陈旧的信息(不一致)。
最后,您可以选择是否希望系统在网络分区下保持强大的一致性或高可用性。
实践表明大多数应用程序更重视可用性。你不一定总是需要很强的一致性。即便如此,这种权衡并不一定是因为您需要100%的可用性保证,而是因为在必须同步机器以实现强大的一致性时,网络延迟可能成为一个问题。这些和更多因素使应用程序通常选择提供高可用性的解决方案。
这些数据库用最弱的一致性模型解决 - 最终的一致性(强大vs最终一致性解释)。此模型保证,如果没有对给定项目进行新更新,则最终对该项目的所有访问都将返回最新的更新值。
这些系统提供BASE属性(与传统数据库的ACID相反)
- 基本可用 - 系统始终返回响应
- 软状态 - 即使在没有输入时(由于最终的一致性),系统也可能随时间而改变,
- 最终一致性 - 在没有输入的情况下,数据迟早会传播到每个节点 - 从而变得一致。
这种可用的分布式数据库的例子 - Cassandra,Riak,Voldemort
当然,还有其他更喜欢更强一致性的数据存储--HBase,Couchbase,Redis,Zookeeper
CAP理论值得自己撰写多篇文章 - 其中一些内容涉及如何根据客户端的行为以及其他如何正确理解它来调整系统的CAP属性。
Distributed Computing
分布式计算是近年来我们见到的大数据处理流入的关键。它是将一项庞大的任务(例如总计1000亿条记录)分割成许多较小的任务的技术,其中任何一台计算机都不能单独执行,而每个任务都可以装入一台商品机器中。您将您的庞大任务分解为许多较小的任务,让它们在多台机器上并行执行,合适地汇总数据,并解决了最初的问题。这种方法再次使您能够水平扩展 - 当您有更大的任务时,只需在计算中包含更多节点。
这个领域的早期创新者是谷歌,因为他们需要大量的数据必须为分布式计算创造一种新的范式 - MapReduce。他们在2004年发表了一篇论文,而开源社区后来又基于它创建了Apache Hadoop。
MapReduce
MapReduce可以简单地定义为两个步骤 - 映射数据并将其减少为有意义的数据。
我们再来看一个例子: 假设我们是中型企业,我们将庞大的信息存储在二级分布式数据库中用于仓储目的。我们希望获取表示2017年4月(一年前)每天发布的拍手次数的数据。
这个例子尽可能简短,清晰和简单,但想象我们正在处理大量数据(例如分析数十亿次拍子)。我们不会将所有这些信息都存储在一台机器上,我们也不会仅用一台机器来分析所有这些信息。我们也不会查询生产数据库,而是专门为低优先级脱机作业构建的一些“仓库”数据库。
每个Map作业都是一个单独的节点,它可以转换尽可能多的数据。每个作业都会遍历给定存储节点中的所有数据,并将其映射到日期和数字的简单元组。然后,三个中间步骤(没人谈论)完成 - Shuffle,Sort和Partition。他们基本上进一步安排数据并将其删除到适当的减少工作。在我们处理大数据时,我们将每个Reduce作业分隔开来,仅在单个日期上工作。
这是一个很好的范例,令人惊讶的是你可以用它做很多事情 - 例如,你可以链接多个MapReduce作业。
Better Techniques
在MapReduce有些遗留问题,并带来一些问题。因为它在批处理(作业)中起作用,所以如果您的工作失败,则会出现问题 - 您需要重新开始整个工作。 2小时的工作失败可能会让你的整个数据处理流程变慢,而且你并不想这么做,特别是在高峰时段。
另一个问题是您等待直到您收到结果的时间。在实时分析系统中(所有这些系统都有大量数据,因此使用分布式计算),重要的是要让您的最新数据尽可能的新鲜,当然不是几个小时前。
因此,出现了解决这些问题的其他体系结构。即Lambda体系结构(混合批量处理和流处理)和Kappa体系结构(仅流处理)。这些领域的进步带来了新的工具 - Kafka Streams,Apache Spark,Apache Storm,Apache Samza。
Distributed File Systems
分布式文件系统可以被认为是分布式数据存储。它们与概念一样 - 在一组机器中存储和访问大量数据,所有这些数据都显示为一个整体。他们通常与分布式计算并驾齐驱。
Wikipedia定义的区别在于分布式文件系统允许使用与本地文件相同的接口和语义来访问文件,而不是像Cassandra查询语言(CQL)那样的自定义API。
HDFS
Hadoop分布式文件系统(HDFS)是通过Hadoop框架用于分布式计算的分布式文件系统。它被广泛采用,用于存储和复制大型文件(大小为GB或TB)跨多台机器。
其架构主要由NameNode和DataNode组成。 NameNode负责保存关于集群的元数据,比如哪个节点包含哪些文件块。他们通过找出最佳存储和复制文件的位置,跟踪系统的健康状况,充当网络的协调员。 DataNodes只是简单地存储文件并执行命令,如复制文件,写入新文件等等。
毫不奇怪,HDFS最适合用于计算,因为它为计算作业提供数据感知。所述作业然后在存储数据的节点上运行。这利用了数据局部性 - 优化了计算并减少了网络上的流量。
IPFS
星际文件系统(IPFS)是一个令人兴奋的新型分布式文件系统对等协议/网络。利用区块链技术,它拥有完全分散的架构,没有单一所有者或故障点。
IPFS提供了一个名为IPNS的命名系统(类似于DNS),可让用户轻松访问信息。它通过历史版本存储文件,类似于Git的做法。这允许访问文件的所有以前的状态。
它仍然在经历重大的发展(写作时的v0.4),但已经看到有兴趣构建它的项目(FileCoin)。
Distributed Messaging
消息传递系统为整个系统内的消息/事件的存储和传播提供了一个中心位置。它们允许您将应用程序逻辑从直接与其他系统交谈中分离出来。
简而言之,消息传递平台的工作原理如下:
消息从可能创建它的应用程序(称为生产者)广播,进入平台并被潜在的多个对其感兴趣的应用程序(称为消费者)读取。
如果您需要将某个事件保存到几个地方(例如创建用户到数据库,仓库,电子邮件发送服务以及任何您可以提供的服务),则消息传递平台是传播该消息的最干净的方式。
消费者可以将信息从经纪人(拉模型)中提取出来,或让经纪人直接将信息推送给消费者(推送模式)。
有几个流行的顶级消息平台:
RabbitMQ - 消息代理,允许您通过路由规则和其他易于配置的设置对消息轨迹进行更细粒度的控制。可以称为智能代理,因为它有很多逻辑,并且密切关注通过它的消息。从CAP提供AP和CP的设置。使用推送模式通知消费者。
Kafka - 消息代理(以及所有平台),它有点低级,因为它不能跟踪哪些消息已被读取,并且不允许复杂的路由逻辑。这有助于它实现惊人的性能。在我看来,这是开源社区积极开发和Confluent团队支持的最大前景。卡夫卡可以说是顶尖科技公司使用最广泛的卡夫卡。我写了一篇全面的介绍,我详细介绍了它的所有优点。
pache ActiveMQ - 最早的一批,从2004年开始。使用JMS API,这意味着它适用于Java EE应用程序。它被改写为ActiveMQ Artemis,与Kafka相媲美,表现出色。
Amazon SQS - 由AWS提供的消息服务。让您可以快速将其与现有应用程序集成,并且无需处理您自己的基础架构,这可能是一个巨大的好处,因为像Kafka这样的系统的安装非常棘手。亚马逊还提供两种类似的服务 - SNS和MQ,后者基本上是ActiveMQ,但由亚马逊管理。
Distributed Applications
如果您在连接到一个数据库的单个负载均衡器后面集合了5个Rails服务器,您能否称为分布式应用程序?从上面回想我的定义:
分布式系统是一组计算机一起工作,以便作为单台计算机显示给最终用户。这些机器具有共享状态,并发操作并可独立故障,而不会影响整个系统的正常运行时间。
如果您将数据库视为共享状态,那么您可以争辩说这可以归类为分布式系统 - 但是您错了,因为您错过了定义的“一起工作”部分。所以这并不能说是分布式系统。
只有当节点相互通信以协调它们的动作时,系统才会被分配。
因此,类似于在对等网络上运行其后端代码的应用程序可以更好地分类为分布式应用程序。无论如何,这都是无用的分类,没有任何用处,但说明我们将事情分组在一起是多么的繁琐。
Summary
在本文短小的篇幅中,我们管理着定义什么是分布式系统,为什么要使用它,并稍微检查每个类别。一些重要的事情要记住的是:
- 分布式系统很复杂
- 他们是根据规模和价格的必然选择
- 他们很难与之合作
- CAP定理 - 一致性/可用性权衡
- 他们有6个类别 - data stores, computing, file systems, messaging systems, ledgers, applications
坦率地说,我们几乎没有触及分布式系统的表面。我没有彻底解决和解释诸如共识,复制策略,事件排序和时间,容错等核心问题的变化,在网络和其他人中广播消息。
Caution 警告
让我留给你一个离别的预警:
你必须尽可能地远离分布式系统。如果您能够以不同的方式或其他现成的解决方案来解决问题,那么它们所带来的复杂性开销就不值得付出努力。