云服务器价格_云数据库_云主机【优惠】最新活动-搜集站云资讯

分布式存储_痞子英雄百度云_超低折扣

小七 141 0

Atomic Multi-Part S3与Consult一起上载

Vagrant Cloud是HashiCorp提供的一种服务,它为Vagrant提供了许多没有服务器组件就无法实现的功能。它的付费功能之一是框托管,允许在流浪云中托管和管理流浪箱。我们已经收到几份报告说,上传非常大的流浪箱将可靠地失败,我们花了上个星期的一部分时间来解决这个问题。我们使用S3作为后备存储,最终发现S3将单个上传的大小限制为5GB。HashiCorp有一个面向服务的基础设施,二进制存储管道涉及我们的BinStore和StorageLocker服务。StorageLocker为我们的二进制存储提供了位置透明性,并使用简单的流式RPC协议。其API包括:Put(键,值)->地址获取(地址)->值删除(地址)这使我们的内部服务能够轻松地存储和检索大的有效负载,而不必担心后端存储系统的具体情况,从而使我们能够执行透明的压缩、缓存、校验和和复制,即使是作为内部部署产品的一部分运行时也是如此。BinStore是一个面向公众的服务,它讲HTTP,并提供了一种向全世界公开StorageLocker的经过身份验证的方法。在这种情况下,修复上载限制的逻辑位置是在StorageLocker中,但即使在这里我们也有选择。我们可以使用本机S3多部分上传API,或者将该逻辑构建到StorageLocker中。使用本机API需要启动上载,上载每个部分,然后完成或中止上载。如果我们斜视一下,这看起来就像一个事务:我们有一个开始,修改一些数据,最后提交或中止。对于单个对象上传,我们自动获得原子性:要么对象上传,要么不上传。但是对于多部分上传,我们引入了部分失败状态。有可能我们的一些部分没有上传,或者他们都上传了,但我们无法提交或中止。StorageLocker有可能崩溃,或者我们的数据中心在上传过程中失去连接。潜在错误案例的数量太多,无法枚举。在传统的RDBMS中,我们的事务发生在与数据库的持久连接的上下文中。如果我们在事务处理过程中失败,数据库将确保事务被中止,从而保持原子性。然而,对于S3,AWS无法检测客户端的故障,它看起来就像是部分完成的上载,并且不会执行自动中止。这使得中止上载和确保原子性成为客户端的问题。AWS提供了一个API来列出任何正在进行的上载,我们可以定期获取并使用它来中止任何等待时间过长的上载。虽然这是一个启发,但不太可能有任何等待数天的上传活动。退一步讲,我们已经确定了只使用s3api就可以实现多部分上传的原子性。但是,所有这些都是S3特有的,包括一个服务来管理中止失败的上传。在这一点上,我们开始考虑其他通用的解决方案,以便与其他存储后端一起使用。如果我们希望mechansim在不知道存储后端的情况下进行多部分上传,那么我们就不能依赖于S3特定的api。这一点尤其重要,因为我们必须保持与本地产品相同的特性,而S3可能不是可用的后备存储。大多数适合流式处理大型二进制文件的键/值存储不公开事务性概念。这意味着我们不能依赖后端为多个密钥提供原子性。»在上面加个墙在数据库世界中,提供原子性通常是一个关键的要求。大多数数据库通过使用一种称为预写日志(Write-Ahead Logging,WAL)的技术来实现这一点。虽然是一口,但背后的直觉很简单:标记你打算做什么,尝试做什么,标记你是成功还是失败。WAL用于从部分故障中恢复,方法是使操作回滚并将状态恢复到原始状态。首先,这看起来是一个适合我们的多部分上传问题的技术。我们只需维护一个WAL的部分上传和恢复从一个部分故障只需要删除部分。然而,我们现在有另一个问题:如果我们失去了有墙的机器呢?在传统数据库的情况下,这一点是没有意义的,因为数据存储在WAL旁边,因此不需要执行清理。如果我们失去了WAL,我们的数据仍然存在于S3中,但现在恢复是不可能的。这就是领事进来的地方。consur是一个服务发现、配置和编排的解决方案。它的关键特性之一是分布式密钥/值存储。consur通过将数据复制到多个节点来确保其管理的数据具有高度可用性和持久性。从客户机的角度来看,我们可以写入它,并确信在节点故障期间不会丢失数据。为了防止丢失运行StorageLocker的节点和WAL,我们只需将WAL存储在consur中。现在,如果处理上载的StorageLocker实例失败,WAL可以通过consur提供给任何其他实例。恢复是通过获取所有过期的wal并从相应的后端删除所有部分来完成的。通过应用基于时间的启发式方法,可以像S3一样管理过期。我们不希望任何上传跨越多天,这使得我们更不可能因为我们提前超时上传。»魔鬼在细节虽然我们已经大致介绍了解决方案,但我们将在细节中精辟地介绍每个操作的细节。从逻辑上讲,我们使用Put操作启动工作流:如果文件大小低于可配置的ChunkSize,请作为单个部分上载,完成。根据ChunkSize计算块数创建一个如下所示的WAL条目:{"ID":"","开始":,"URL":["",...,"","元数据文件"],}将WAL条目写入consur(我们将其存储在service/storagelocker/WAL/)上传所有部件编写元数据文件,该文件包含文件大小、校验和以及所有部分的地址。删除我们的WAL条目,这是我们的承诺。如果在任何步骤中遇到错误,请中止上载,删除所有部分,然后删除WAL。这是我们的原子上传的伪代码。我们使用预写日志,这样我们就可以安全地回滚任何部分上传,并且我们将日志存储在consur上以防止节点故障。为了处理节点故障,我们的所有StorageLocker实例都会定期扫描废弃的WAL条目,然后转到步骤8,调用相同的错误处理逻辑。删除键也有同样的问题,因为我们不想保留部分删除的对象。处理delete类似于put:如果文件只有一个部分,请正常删除,完成。获取元数据文件(由URL指定)。创建一个WAL条目,格式与Put完全相同,只是url是由元数据文件而不是计算出来的,并包含元数据文件。给领事写封信删除所有部件,包括元数据文件。删除我们的WAL条目,提交删除。如果遇到错误,请中止删除,并调用恢复逻辑。在这种情况下,可能需要稍后使用内置的标准WAL恢复重试删除。通过让Put和Delete对WAL条目使用相同的格式,我们可以使用相同的恢复逻辑。幸运的是,这两种类型的故障的恢复都是简单地删除所有相应的部分。最后一个操作是Get,因为它是幂等的,所以要简单得多。这意味着在发生错误时不需要清理或恢复逻辑,因此流程简单如下:如果文件只有一个部分,请正常获取它。获取元数据文件(由URL指定)。按顺序获取每个零件。在StorageLocker中,我们使用一个引擎接口,其中每个具体实现都用于特定的后端。例如,S3Engine在S3中存储数据。通过实现WALEngine,我们可以将其与任何其他引擎组合在一起,使我们的所有后端都能够透明地支持多部分上传,而不会牺牲原子性。我们对StorageLocker的更改已经实施并推广到了Vagrant Cloud,所以很高兴上传!