写点什么

Magic Pocket:Dropbox 的 EB 级 Blob 存储系统

作者:Facundo Agriel

  • 2023-07-26
    北京
  • 本文字数:4405 字

    阅读完需:约 14 分钟

Magic Pocket:Dropbox的EB级Blob存储系统

在旧金山 QCon 大会上,我介绍了 Dropbox 的 EB 级 Blob 存储系统是如何存储所有客户数据的。Magic Pocket的核心是一个非常大的键值存储,其中的值可以是任意大小的 Blob。

 

我们的系统提供了超过 12 个 9 的持久性和 99.99%的可用性,在北美的三个地理区域运营。系统针对 4BM Blob、不可变写入和冷数据做了优化。

 

Magic Pocket 每秒处理数千万个请求,其中很多流量来自验证器和后台迁移。目前,我们部署了 60 多万个存储驱动器,运行着数千台计算机。

 

对象存储设备


Magic Pocket 主要聚焦对象存储设备(OSD)。这些设备的容量超过 2PB,每台存储机包含大约 100 块采用了叠瓦式记录(SMR)技术的磁盘。

 

与传统的磁记录驱动器相比,SMR 的不同之处在于它执行顺序写入而不是随机写入,提升了密度。

 

SMR 的缺点是,磁头会在走过下一条磁道时擦除它,以防在任何地方随机写入。

 

不过,这非常适合我们的工作负载模式。SMR 驱动器也有一个传统区域,允许在必要时缓存随机写操作。通常,该区域占驱动器总容量的不到 1%。



图 1:SMR 磁道布局

 

宏观上,Magic Pocket 的架构由三个区域组成:西海岸、中部和东海岸。Pocket 是该系统的核心概念,它代表了系统中所有东西的逻辑版本。Magic Pocket 可以有多个实例,如测试 Pocket 或生产 Pocket 之前的过渡 Pocket。Pocket 是独立运行的,彼此之间不共享数据库和计算资源。

区域


以下是每个区域中 Magic Pocket 架构的不同组件。



图 2:区域的工作机制

 

第一个服务是前端,它是与客户端交互的服务。客户端通常会发起 PUT 请求(带有键和 Blob)、GET 请求、删除调用或扫描系统中可用的散列。

 

GET 请求会查询散列索引(分片 MySQL 数据库的集合)。散列索引按散列分片,散列是 Blob 的键,每个散列都映射到一个单元格(cell)或一个桶(bucket),并有一个校验和。单元格是所有存储设备所在的隔离单元:它们可以超过 100PB,并且规模上有一定的增长空间。当容量不足时,系统将开辟一个新的单元格,实现水平扩展。

 

跨区域复制器是执行跨区域复制的组件,可以将数据存储在多个区域。该操作是异步完成的,一旦主区域发生了提交,数据就会排队等待复制到另一个区域。控制平面管理流量协调、生成迁移计划并控制机器重装。它还管理着单元格状态信息。

单元格


如果想获取一个 Blob,就需要访问了解桶和卷的桶服务:当请求一个桶时,请求会被映射到一个卷,而这个卷会被映射到一组 OSD。



图 3:单元格的运作机制

 

一旦找到拥有所需 Blob 的 OSD,就可以检索它了。对于写入数据,前端服务会找出哪些桶是打开的,并提交给处于就绪状态的桶。桶是预先创建好的,数据存储在卷内的一组 OSD 中。

 

协调器是单元格中的一个重要组件,管理所有桶、卷和存储机。协调器不断检查存储机的运行状况,与桶服务和数据库协调信息,并执行擦除编码和修复:它通过在单元格内移动数据实现数据优化,并负责在必要时将数据移动到其他机器。卷管理器处理卷的读、写、修复和擦除编码。验证步骤在计算单元格内外都会执行。

桶、卷和区段


现在,我们可以更深入地研究 Magic Pocket 存储系统的组件了,即桶、卷和区段。



图 4:桶、卷和区段

 

桶是与卷和区段相关联的逻辑存储单元,代表磁盘上 1 到 2GB 的数据。当写入时,我们找到打开的桶和与之关联的 OSD,然后写入区段。协调器管理桶、卷和区段信息,并可以通过为已删除的区段找到新的位置确保数据不会丢失。一个卷由一个或多个桶组成,它要么被复制,要么被擦除编码,它的状态可以是打开或关闭。一旦一个卷关闭后,就再也不会打开了。

如何在对象存储设备上查找 Blob


在这一部分中,我们将介绍如何在存储机中查找 Blob。为此,我们将 OSD 的地址存储在 Blob 中,并直接与这些 OSD 通信。



图 5:查找 Blob

 

磁盘驱动器(OSD)会加载所有区段信息,并创建一个内存索引,其中有磁盘偏移量的哈希值。如果想要获取块,就需要知道卷以及哪些 OSD 拥有该 Blob。对于 PUT,过程是一样的,但我们是并行地对每个 OSD 进行写操作,并且要在所有存储机上的写操作都完成后才会返回。由于卷被复制了 4 份,所以所有四个 OSD 中都有完整的副本。

擦除编码


虽然故障不可避免,但 2 个区域 4 个副本的复制成本很高。我们来看一下复制卷和擦除编码卷之间的区别,以及如何处理它。



图 6:擦除编码

 

擦除编码可以降低复制成本,并保持与复制相似的持久性。在我们的系统中,当一个卷快满了的时候,它就会关闭,就可以进行擦除编码。我们使用了一个擦除码,就像Reed-Solomon误码校正编码(6,3),在一个卷组中有 6 个 OSD 和 3 个奇偶校验位。这是说,在一个数据区段中只有一个 Blob,如果一个 OSD 出现故障,则可以重建它。重建可以发生在对数据的实时请求中,也可以作为修复的一部分在后台完成。擦除码有许多变体,它们在开销方面有各自的考量,例如,使用 XOR 作为擦除码可能很简单,但自定义擦除码可能更合用。



图 7:故障和擦除编码

 

关于这个主题,Huang 等人的论文“Windows Azure存储中的擦除编码”是一份不错的资源,我们的系统就使用了类似的技术。



图 8:Huang 等人的论文“Windows Azure存储中的擦除编码”中的 Reed-Solomon 误码校正编码

 

我在前面的例子中提到过的 Reed-Solomon 纠错码(6,3),有 6 个数据区段和 3 个奇偶校验位。另一个选项为本地重建代码,它优化了读取成本。Reed-Solomon 纠错码(6,3)在出现任何故障时都要读取 6 次。但是,使用本地重建代码,对于同一类型的数据故障,虽然读取成本相同,但是与 Reed Solomon 的 1.5 倍复制因子相比,存储开销大约降低了 1.33 倍。虽然这看起来差别不大,但当规模比较大时,却可以节省大量的资金。



图 9:Huang 等人的论文“Windows Azure存储中的擦除编码”中的重建代码比较

 

本地重建代码针对组中出现一个故障的情况做了优化,生产环境中经常会遇到这种情况。做出这种权衡是可以接受的,因为在一个卷组中出现 2 个以上故障的情况很少见。

 

这些编码的复制因子甚至可以更低:编码 LRC-(12,2,2)可以容忍组内有三个故障,但不能容忍四个,此时只有部分故障可以重建。

冷存储系统


我们的系统还能做得更好吗?正如我们观察到的那样,90%的检索是针对去年上传的数据,80%的检索发生在前 100 天内,我们正在探索改进跨区域复制的方法。



图 10:文件访问分布

 

我们有大量不经常访问的冷数据,因此,我们希望优化工作负载,减少读取,并保持延迟、持久性和可用性基本不变。根据我们的观察,为了实现这一点,我们不必对冷存储进行实时写入,并且可以利用多个区域将复制因子降至 2x 以下。

 

让我们看一下我们的冷存储系统是如何工作的,其灵感来自 Facebook 的暖Blob存储系统。这篇有关 f4 的论文提出了一种方法,将一个 Blob 分成两半(分别存储在不同的区域),并对这两半做XOR。要检索完整的 Blob,Blob1 和 Blob2 的任意组合或 XOR 就必须在任意两个区域中可用。但是,要执行写入操作,所有区域都需要完全可用。请注意,由于迁移是在后台异步进行的,所以它们不会影响实时进程。



图 11:分割 Blob 和冷存储

 

这种冷存储系统有什么好处呢?通过将复制因子从 2x 降低到 1.5x,我们节省了 25%的成本。存储在冷存储中的片段仍然会在内部进行擦除编码,并且迁移是在后台进行的。为了减少主干带宽的开销,我们将请求发送到两个最近的区域,并且只在必要的时候才从其他区域获取。这又节省了大量的带宽。

发布周期


Magic Pocket 是如何发布的?从所有过渡环境到生产环境,我们的发布周期大约为四周。



图 12:Magic Pocket 的发布周期

 

在提交更改之前,我们会运行一系列单元测试和集成测试,包含所有的依赖项,以及一个对所有数据进行全面验证的持久性阶段。每个区域在每个阶段都会进行大约一周的验证:我们的发布周期是完全自动化的,它会做适当的检查,如果有任何警告,它就会中止或不再继续更改代码。只有在特殊情况下,我们才会停止自动部署过程,并人为干预。

验证


那么验证呢?在系统内部,为了确保数据的准确性,我们做了大量的验证。



图 13:验证

 

其中一项是由跨区域验证器执行的,它负责在上游客户端和系统之间同步数据映射。另一个是索引验证器,它会扫描索引表,确认每台存储机中是否存在特定的 Blob:我们只是询问存储机已加载的区段询中是否有这个 Blob,而不获取实际的内容。观察器是另一个会对 Blob 本身进行全面验证的组件,按分钟、小时、天和周进行采样。我们还有一个垃圾检查器,确保区段被删除后,其中的所有散列都会被删除。

 

运营


因为 Magic Pocket 跨多个数据中心,所以我们要处理大量的迁移。我们管理着一个非常大的存储机机群,知道每时每刻都发生了什么非常重要。混乱时有发生,我们会通过大量的灾难恢复活动来测试系统的可靠性:升级这种规模的系统和系统本身一样困难。管理后台流量是我们的关键运营工作之一,因为那占用了我们大部分的流量和磁盘 IOPS。磁盘洗涤器不间断地扫描所有流量并检查区段的校验和。我们根据业务将流量划分为不同的层,并根据网络情况对实时流量做优先级排序。

 

控制平面会根据我们对数据中心迁移所做的预测来规划大量的后台流量:我们会考虑正在进行的迁移类型,如冷存储,并相应地制定计划。

 

系统中有许多故障需要我们处理:我们每秒要修复 4 个区段,大小从 1GB 到 2GB 不等。我们有相当严格的 SLA(少于 48 小时),因为那是我们持久性模型的组成部分,我们希望尽可能地缩短修复时间。OSD 会根据单元格的大小和当前的利用率自动分配到系统中。

 

我们也有很多向不同数据中心的迁移。



图 14:迁移

 

两年前,我们迁出了 SJC 地区,为此我们做了大量的计划。对于非常大的迁移,比如数百个 PB,幕后会有大量的准备工作,我们会给自己额外留出时间,以确保迁移能够及时完成。

 

预测


在管理这种规模的存储系统时,预测是一个很关键的部分。我们一直在应对存储增长的挑战,有时可能是意料之外的,那就需要我们能够快速做出调整并将新的数据接收到我们的系统中。此外,我们可能会因为供应链中断(如 COVID 大流行造成的供应链中断)而面临容量问题:一旦发现潜在的问题,我们就会开始制定备份计划,因为订购并向数据中心交付新容量需要相当长的时间。我们的预测直接集成到了控制平面中,这有助于我们根据容量团队提供的信息执行迁移。

 

小结


在维护 Magic Pocket 的过程中,我们总结出了以下 4 条关键的经验:

  • 保护和验证

  • 规模比较大时要慢慢来

  • 保持简单

  • 做最坏的打算

 

首先,我们要优先考虑系统的保护和验证。这需要大量的开销,但端到端验证对于确保一致性和可靠性至关重要。

 

在这种规模下,要慢慢来,稳定很重要。我们要优先考虑持久性,部署任何新内容之前都要等待验证完成。我们总是会考虑风险,为最坏的情况做准备。

 

简单性也是一个关键因素。我们的目标是保持简单,特别是在大规模迁移期间,因为过多的优化可能会导致复杂的心智模型,增加计划和调试的难度。

 

此外,我们总会准备一个备份计划,以防在迁移或部署期间出现故障或问题。我们会确保变更不是单向的,必要时可以逆转。总体而言,管理这种规模的存储系统需要综合考量保护、验证、简单性和准备工作等诸多方面。

 

原文链接:

https://www.infoq.com/articles/dropbox-magic-pocket-exabyte-storage/

2023-07-26 08:002350

评论

发布
暂无评论
发现更多内容

【Vue2.x 源码学习】第三篇 - 对象的单层劫持

Brave

源码 vue2 6月日更

NCRE考试感想 三级信息安全(上)

万里无云万里天

信息安全 6月日更 NCRE 考试经验

获5项大奖,发布《云计算开放应用架构标准》,阿里云持续领航云原生

阿里巴巴中间件

踩准时钟节拍、玩转时间转换,鸿蒙轻内核时间管理有妙招

华为云开发者联盟

鸿蒙 时间管理 计数器 时间转换 计时

PMP-项目管理标准

索隆

pmp 6月日更

react源码解析5.jsx&核心api

全栈潇晨

React React Hooks

详解浏览器跨域访问的几种办法

华为云开发者联盟

安全 浏览器 跨域 WEB安全 跨域访问

Overbit Flash|5 月加密货币市场风暴抹去了 90% 以上的 NFT 交易量

Overbit学院

比特币 加密货币 NFT Overbit 保证金交易

华云大咖说 | 安超OS全面升级 最新亮点解密

华云数据

🏆【声网Agora】「WebRTC-如何搭建语音认证服务」

洛神灬殇

WebRTC RTC征文大赛 Agora 6月日更

傲腾持久内存如何为数据赋能,加速应用落地?

白玉兰开源

人工智能 英特尔 傲腾

Golang Testing 概览 - 基本篇

hedzr

Unit Test testing Go 语言

C 语言数据结构的封装方法

实力程序员

裕民银行 x mPaaS | 移动应用“适老化”改造,可不止是字体变大

蚂蚁集团移动开发平台 mPaaS

移动开发 mPaaS APP开发

和12岁小同志搞创客开发:如何驱动各类型传感器?

不脱发的程序猿

DIY 传感器 如何驱动各类型传感器? 创客

超超超超级详细的多边形游戏问题分析(动态规划)

若尘

算法 动态规划 6月日更

5W1H聊开源之What——开源是什么?

禅道项目管理

开源 软件 开发

【通俗易懂】JWT-使用的可能正确姿势

蛋先生DX

JWT 6月日更

有点难的知识点:Webpack Chunk 分包规则详解

范文杰

webpack 6月日更

6000年,看懂了「硬核山东」!

浪潮云

云计算

亮相Google I/O,字节跳动是这样应用Flutter的

字节跳动技术团队

如履薄冰--亚马逊直运系统重构实录

蔡超

软件架构 软件重构 软件自动化测试

【Flutter 专题】113 图解自定义 ACEPieWidget 饼状图 (二)

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 6月日更

为鸿蒙OS说两句公道话(我对鸿蒙OS的一些看法)

Phoenix

ETL工程师必看!超实用的任务优化与断点执行方案

TASKCTL

大数据 ETL算法 ETL ETL任务 ETL系统

Dubbo 线程池模型

青年IT男

dubbo

分库分表 vs NewSQL 数据库

xcbeyond

分库分表 6月日更

音视频学习--弱网对抗技术相关实践

Fenngton

音视频 网络 视频编解码 弱网下的极限实时视频通信 实时视频

C++多线程强制终止

华为云开发者联盟

c++ 安全 线程 多线程 可信

anyRTC Web SDK 实现音视频呼叫功能

anyRTC开发者

音视频 WebRTC RTC sdk

【LeetCode】连续数组Java题解

Albert

算法 LeetCode 6月日更

Magic Pocket:Dropbox的EB级Blob存储系统_服务革新_InfoQ精选文章