Swift 架构概述¶
代理服务器¶
代理服务器负责将 Swift 架构的其余部分连接在一起。对于每个请求,它将在环中(如下所示)查找帐户、容器或对象的位置,并相应地路由请求。对于 Erasure Code 类型策略,代理服务器还负责编码和解码对象数据。有关 Erasure Code 支持的完整信息,请参阅 Erasure Code 支持。
代理服务器还处理大量故障。例如,如果服务器无法用于对象 PUT,它将要求环提供一个切换服务器并路由到那里。
当对象通过对象服务器流式传输时,它们会直接通过代理服务器流式传输到用户或从用户流式传输 – 代理服务器不会缓冲它们。
环¶
环表示磁盘上存储的实体名称与其物理位置之间的映射。帐户、容器和每个存储策略都有单独的环。当其他组件需要对对象、容器或帐户执行任何操作时,它们需要与适当的环交互以确定其在集群中的位置。
环使用区域、设备、分区和副本来维护此映射。环中的每个分区默认在整个集群中复制 3 次,并且分区的存储位置存储在环维护的映射中。环还负责确定在发生故障时用于切换的设备。
每个分区的副本将隔离到尽可能多的不同区域、区域、服务器和设备上,这些故障域的容量允许。如果给定层级的故障域少于分配在该层级内的分区副本数(例如,一个具有 2 个服务器的 3 副本集群),或者给定层级内的故障域之间的可用容量不平衡,则将无法同时实现均匀的容量分布(balance)以及故障域之间的完全隔离(dispersion)。当发生这种情况时,环管理工具将显示警告,以便操作员评估集群拓扑。
数据根据设备权重在集群中可用的容量上均匀分布。权重可用于平衡集群中驱动器上的分区分布。例如,当集群中使用不同大小的驱动器时,这会很有用。在添加或删除容量或故障域时,设备权重也可用于控制在重新平衡期间要移动的分区数量,以便在复制带宽允许的情况下尽快移动。
注意
在 Swift 2.1.0 之前,在添加新的故障域时无法通过设备权重限制分区移动,并且会允许环严重不平衡。贪婪的离散算法现在受到系统中物理容量的约束,但可以通过超载选项在合理范围内进行调整。不尊重容量而人为地使分区分配不平衡可能会在给定故障域在层级中物理上无法支持其使用的容量份额时引入意外的设备已满的情况。
当需要移动分区时(例如,如果将设备添加到集群),环可确保一次移动最少数量的分区,并且一次只移动一个分区副本。
环由代理服务器和几个后台进程(如复制)使用。有关环的完整信息,请参阅 环。
存储策略¶
存储策略为对象存储提供商提供了一种区分 Swift 部署的服务级别、功能和行为的方式。Swift 中配置的每个存储策略都通过抽象名称暴露给客户端。系统中的每个设备都分配到一个或多个存储策略。这是通过使用多个对象环来实现的,其中每个存储策略都有一个独立的物环,该环可能包括实现特定差异的硬件子集。
例如,可以拥有默认策略,采用 3 倍复制,并创建第二个策略,该策略仅对新容器使用 2 倍复制。另一种方法是将 SSD 添加到一组存储节点,并为某些容器创建性能层存储策略,以将对象存储在那里。还有一种方法是使用 Erasure Coding 来定义冷存储层。
此映射随后在每个容器的基础上公开,每个容器可以在创建时分配特定的存储策略,该策略在容器的整个生命周期内保持有效。应用程序需要最少的存储策略意识才能使用它们;一旦容器使用特定策略创建,存储在其中的所有对象都将按照该策略进行存储。
存储策略功能在整个代码库中实现,因此它是理解 Swift 架构的重要概念。
有关存储策略的完整信息,请参阅 存储策略。
对象服务器¶
对象服务器是一个非常简单的 blob 存储服务器,可以存储、检索和删除存储在本地设备上的对象。对象作为二进制文件存储在文件系统上,元数据存储在文件的扩展属性 (xattrs) 中。这要求对象服务器的底层文件系统选择支持文件上的 xattrs。某些文件系统,如 ext3,默认情况下已关闭 xattrs。
每个对象都使用从对象名称的哈希和操作的时间戳派生的路径存储。最后写入总是胜出,并确保提供最新的对象版本。删除也被视为文件的一个版本(以“.ts”结尾的 0 字节文件,代表墓碑)。这确保已删除的文件被正确复制,并且旧版本不会由于故障场景而神奇地重新出现。
容器服务器¶
容器服务器的主要工作是处理对象列表。它不知道这些对象在哪里,只是知道特定容器中的哪些对象。列表存储为 sqlite 数据库文件,并以类似于对象复制的方式在整个集群中复制。还跟踪统计信息,包括容器中的对象总数和总存储使用量。
帐户服务器¶
帐户服务器与容器服务器非常相似,除了它负责容器列表而不是对象列表。
复制¶
复制旨在在临时错误条件(如网络中断或驱动器故障)的情况下使系统保持一致状态。
复制过程将本地数据与每个远程副本进行比较,以确保它们都包含最新版本。对象复制使用哈希列表快速比较每个分区的部分,而容器和帐户复制使用哈希和共享高水位线组合。
复制更新是基于推送的。对于对象复制,更新只是将文件 rsync 到对等方。帐户和容器复制通过 HTTP 或 rsync 整个数据库文件推送缺失的记录。
复制器还确保从系统中删除数据。当项目(对象、容器或帐户)被删除时,将墓碑设置为该项目的最新版本。复制器将看到墓碑并确保该项目从整个系统中删除。
有关复制的完整信息,请参阅 复制。
重建¶
重构器由 Erasure Code 策略使用,并且类似于复制类型策略的复制器。有关 Erasure Code 支持以及重构器的完整信息,请参阅 Erasure Code 支持。
更新器¶
有时无法立即更新容器或帐户数据。这通常发生在故障场景或高负载期间。如果更新失败,则更新将本地排队到文件系统上,并且更新器将处理失败的更新。这通常是最终一致性窗口出现的地方。例如,假设容器服务器负载过重,并且将新对象放入系统。一旦代理服务器向客户端响应成功,该对象将立即可用于读取。但是,容器服务器未更新对象列表,因此更新将排队以供以后更新。因此,容器列表可能不会立即包含该对象。
实际上,一致性窗口仅与更新器运行的频率一样大,甚至可能不会注意到,因为代理服务器会将列表请求路由到第一个响应的容器服务器。负载下的服务器可能不是处理后续列表请求的服务器 – 其他两个副本中的一个可能会处理列表请求。
审计器¶
审计器会爬取本地服务器,检查对象、容器和帐户的完整性。如果发现损坏(例如,位腐烂),则该文件将被隔离,并且复制将从另一个副本替换该坏文件。如果发现其他错误,它们将被记录(例如,无法在应找到它的任何容器服务器上找到对象的列表)。