组件¶
对象存储使用以下组件来提供高可用性、高持久性和高并发性
代理服务器 - 处理所有传入的 API 请求。
环 (Rings) - 将数据的逻辑名称映射到特定磁盘上的位置。
区域 (Zones) - 将数据与其他区域隔离。一个区域的故障不会影响集群的其余部分,因为数据会在区域之间复制。
账户和容器 - 每个账户和容器都是分布在集群中的独立数据库。账户数据库包含该账户中的容器列表。容器数据库包含该容器中的对象列表。
对象 - 数据本身。
分区 (Partitions) - 分区存储对象、账户数据库和容器数据库,并帮助管理数据在集群中的位置。
对象存储构建块
代理服务器¶
代理服务器是对象存储的公共接口,处理所有传入的 API 请求。一旦代理服务器收到请求,它将根据对象的 URL 确定存储节点,例如:https://swift.example.com/v1/account/container/object。代理服务器还协调响应、处理故障和协调时间戳。
代理服务器使用共享无状态架构,可以根据预计的工作负载进行扩展。应在独立管理的负载均衡器后部署至少两个代理服务器。如果一个代理服务器发生故障,其他服务器将接管。
环 (Rings)¶
环表示集群中存储的实体名称与其在磁盘上的物理位置之间的映射。对于账户、容器和对象,都有单独的环。当系统的组件需要对对象、容器或账户执行操作时,它们需要与相应的环交互以确定集群中的适当位置。
环使用区域、设备、分区和副本来维护此映射。环中的每个分区默认在集群中复制三次,分区位置存储在环维护的映射中。环还负责确定在故障场景中用作交接的设备。
数据可以在环中隔离到区域。每个分区副本将尝试驻留在不同的区域。一个区域可以代表一个驱动器、一台服务器、一个机柜、一个交换机,甚至一个数据中心。
环的分区分布在对象存储安装的所有设备上。当需要移动分区时(例如,如果将设备添加到集群),环确保一次移动最少数量的分区,并且一次只移动一个分区副本。
可以使用权重来平衡集群中驱动器上分区分布。例如,当在集群中使用不同大小的驱动器时,这会很有用。
环被代理服务器和几个后台进程(如复制)使用。
环
这些环由外部管理。服务器进程本身不会修改环,而是由其他工具修改后的新环提供。
环使用路径的 MD5 哈希中的可配置数量的位作为指定设备的分区索引。哈希保留的位数称为分区幂,2 的分区幂次方表示分区计数。对整个 MD5 哈希环进行分区允许集群的其他部分一次处理一批项目,最终效率更高,或者至少比单独处理每个项目或一次处理整个集群更简单。
另一个可配置值是副本计数,它指示构成单个环的分配-设备分配的数量。对于给定的分区索引,每个副本的设备将不会与任何其他副本的设备位于同一区域。可以使用区域根据物理位置、电源隔离、网络隔离或任何其他可以同时提高多个副本可用性的属性来对设备进行分组。
区域 (Zones)¶
对象存储允许配置区域以隔离故障边界。如果可能,每个数据副本都位于单独的区域。在最小级别,一个区域可以是单个驱动器或几个驱动器的分组。如果有五台对象存储服务器,那么每台服务器将代表自己的区域。更大的部署将拥有整个机架(或多个机架)的对象服务器,每个机架代表一个区域。区域的目标是允许集群承受存储服务器的重大故障,而不会丢失所有数据副本。
区域 (Zones)
账户和容器¶
每个账户和容器都是分布在集群中的独立 SQLite 数据库。账户数据库包含该账户中的容器列表。容器数据库包含该容器中的对象列表。
账户和容器
为了跟踪对象数据位置,系统中的每个账户都有一个数据库,该数据库引用其所有容器,而每个容器数据库引用每个对象。
分区 (Partitions)¶
分区是存储数据的集合。这包括账户数据库、容器数据库和对象。分区是复制系统的核心。
将分区视为在履行中心仓库中移动的箱子。单个订单被扔进箱子。系统将该箱子视为一个连贯的实体,因为它在整个系统中移动。箱子比许多小东西更容易处理。它减少了系统中的活动部件。
系统复制器和对象上传/下载在分区上运行。随着系统扩展,其行为仍然可预测,因为分区数量是固定的。
实现分区在概念上很简单:分区只是磁盘上的一个目录,以及一个对应于其包含内容的哈希表。
分区
复制器¶
为了确保数据在所有地方都有三个副本,复制器会持续检查每个分区。对于每个本地分区,复制器都会将其与另一个区域中的复制副本进行比较,以查看是否存在任何差异。
复制器通过检查哈希来了解是否需要进行复制。为每个分区创建一个哈希文件,其中包含分区中每个目录的哈希值。对于给定的分区,将比较每个分区副本的哈希文件。如果哈希值不同,则需要进行复制,并且需要复制的目录将被复制。
这就是分区发挥作用的地方。有了更少的东西在系统中,更大的数据块会被转移(而不是大量的少量 TCP 连接,这效率低下),并且有固定数量的哈希值需要比较。
集群具有最终一致性行为,旧数据可能会从错过更新的分区提供,但复制将导致所有分区收敛到最新数据。
复制
如果一个区域停止工作,包含副本的一个节点会注意到并主动将数据复制到交接位置。
用例¶
以下部分显示了对象上传和下载的用例,并介绍了组件。
上传¶
客户端使用 REST API 向 HTTP 发送请求,以将对象放入现有的容器中。集群接收请求。首先,系统必须弄清楚数据将去哪里。为此,使用账户名称、容器名称和对象名称来确定对象应驻留的分区。
然后环中的查找确定包含相关分区的存储节点。
然后将数据发送到每个存储节点,并在适当的分区中放置。在通知客户端上传成功之前,必须成功完成至少两次写入。
接下来,异步更新容器数据库以反映其中有一个新对象。
对象存储的使用
下载¶
收到一个请求,获取账户/容器/对象。使用相同的哈希一致性,确定分区索引。环中的查找揭示了包含该分区的存储节点。向其中一个存储节点发出请求以获取对象,如果失败,则向其他节点发出请求。