ITPub博客

首页 > IT基础架构 > 服务器/存储 > IO 设备与延迟 — PlanetScale

IO 设备与延迟 — PlanetScale

服务器/存储 作者:ITPUB社群 时间:1970-01-01 08:33:45 0 删除 编辑

非易失性存储是现代计算机系统的基石。每一张现代照片、电子邮件、银行余额、医疗记录以及其他关键数据都保存在数字存储设备上,通常还会多次复制以增强持久性。

非易失性存储,通俗地称为“磁盘”,即使所连接的计算机断电也能存储二进制数据。计算机还有其他形式的易失性存储,如 CPU 寄存器、CPU 缓存和随机存取存储器,它们速度更快,但需要持续供电才能工作。

在这里,我们将通过有趣且可交互的可视化元素,介绍计算历史上非易失性存储设备的历史、功能和性能。这篇博客是为了庆祝我们最新产品发布:PlanetScale Metal。Metal 使用本地连接的 NVMe 驱动器来运行你的云数据库,而不是大多数云数据库提供商使用的较慢且一致性较差的网络附加存储。这带来了极快的查询速度、低延迟和无限的 IOPS。查看文档以了解更多信息。

磁带存储

早在 20 世纪 50 年代,计算机就开始使用磁带驱动器进行非易失性数字存储。多年来,磁带存储系统以多种形态被生产出来,从占据整个房间的大型设备到可以放进口袋的小型驱动器,例如标志性的 Sony Walkman。磁带读取器是一个包含专门设计用于读取磁带盒的硬件的盒子。磁带盒插入后会被展开,使磁带经过 IO 磁头,从而可以读取和写入数据。

尽管磁带在 70 多年前就开始用于存储数字信息,但如今在某些应用中仍在使用。标准的 LTO 磁带盒有数百米长、0.5 英寸宽的磁带。磁带沿其长度方向有多条轨道,每条轨道又进一步划分为许多小单元。一个磁带盒包含数万亿个单元。

每个单元的磁极化方向可以设置为向上或向下,分别对应二进制 0 或 1。从技术上讲,两个单元之间的过渡所产生的磁场才决定了 1 或 0。磁带上一长串比特形成一页数据。在磁带读取器的可视化中,我们简化了这一点,将磁带显示为简单的数据页序列,而不是显示单个比特。

当需要读取磁带时,它会被加载到读取器中,有时是手动加载,有时是机器人加载。然后读取器用电动机旋转磁带盒,并使用读取头在磁带经过下方时读取二进制值。

试试下面这个(大幅减速的)交互式可视化。如果你希望更快或更慢,可以控制磁带的速度。你还可以发出读取请求和写入请求,然后监控它们需要多长时间。你还能看到待处理的 IO 操作队列出现在左上角。尝试发出几个请求,感受一下磁带存储的工作原理:

如果你花足够的时间研究这个,你会注意到:

  • 如果你读写“靠近”读头的单元,速度很快。

  • 如果你读写“远离”读头的单元,速度很慢。

即使使用现代磁带系统,读取磁带上距离较远的数据也可能需要数十秒,因为可能需要将磁带旋转数百米才能到达所需数据。让我们再比较两个更具体的交互示例,以进一步说明这一点。

假设我们需要总共读取 4 页,并额外写入 4 页的数据。在第一种场景中,我们需要读取的全部 4 页都按整齐的顺序排列,而要写入的 4 页紧接在读取之后。你可以在左上角的白色容器中看到排队等待的 IO 操作。请点击 Time IO 按钮查看实际操作,并观察完成所需的时间。

如你所见,大约需要 3-4 秒。在真实系统中,如果 IO 头运行得快得多,并且电机能更快地驱动卷轴,那么速度会快得多。

现在考虑另一种场景:我们需要读写相同数量的页。然而,这些读写分散在整条磁带上。请再次点击 Time IO 按钮。

在读写总数相同的情况下,这花费了约 7 倍的时间!想象一下,如果这个系统被用来加载你的社交媒体信息流或电子邮件收件箱,可能需要数十秒甚至整整一分钟才能显示出来。这将是完全不可接受的。

尽管随机读写的延迟很差,但磁带系统在按长序列读取或写入数据时运行得相当好。事实上,磁带存储在现代技术世界中今天仍然有许多这样的用例。磁带特别适合需要海量存储、不需要频繁读取但需要安全保存的场景。这是因为与竞争对手固态硬盘和硬盘驱动器相比,磁带每 GB 成本更低,并且保质期更长。例如,CERN 拥有一个磁带存储数据仓库,管理着超过 400 PB 的数据。AWS 也提供磁带归档即服务。

磁带不适合的是高流量事务型数据库。对于这些以及许多其他高性能任务,需要其他存储介质。

硬盘驱动器

存储技术的下一个重大突破是硬盘驱动器。

我们不再将二进制数据存储在磁带上,而是将它们存储在一个称为盘片的小型圆形金属磁盘上。该磁盘被放置在一个带有特殊读/写头的 enclosure 内,并以非常高的速度旋转(例如,7200 RPM 很常见)。与磁带一样,该磁盘也被划分为磁道。然而,这些磁道是圆形的,并且单个磁盘通常会有远超 100,000 条磁道。每条磁道包含数十万个页,每个页包含 4k(左右)的数据。

HDD 需要读取器和盘片都进行机械旋转运动,才能将数据带到正确的读取位置。HDD 相对于磁带的一个优势是,比特的整个表面积 100% 的时间都可用。将针头移动并旋转磁盘到正确位置进行读取或写入仍然需要时间,但它不需要像磁带那样被“揭开”。再加上有两个不同的部件可以旋转,这意味着数据可以以低得多的延迟进行读写。典型的随机读取可以在 1-3 毫秒内完成。

下面是一个交互式硬盘。如果你愿意,可以控制盘片旋转的速度,使其更快或更慢。你可以请求硬盘读取一个页面,并写入一个附近可用的页面。如果你在前一个请求完成之前就请求读取或写入,就会形成一个队列,磁盘会按照接收请求的顺序处理它们。和之前一样,你也能在白色的 IO 队列框中看到待处理的 IO 操作队列。

与磁带一样,盘片旋转的速度已被降低了几个数量级,以便更容易看清正在发生的事情。在真实的磁盘中,还会有更多的磁道和扇区,在某些情况下足以存储数 TB 的数据。

让我们再次考虑几个具体场景,看看读取和写入的顺序如何影响延迟。

假设我们总共需要写入三页数据,然后再读取 3 页。这三次写入将发生在附近可用的页面上,而读取将来自磁道 1、4 和 3。请继续点击 Time IO 按钮。你会看到请求进入队列,读取和写入得到完成,然后是最后的总时间。

由于这些操作大多是顺序进行的,所有任务都能很快完成。

现在考虑同样的 6 次读取和写入,但它们以不同的顺序交错进行。请再次点击 Time IO 按钮。

如果你有耐心等到最后,你应该会注意到,同样总数的读取和写入却花费了长得多的时间。大量时间都花在等待盘片旋转到读头下方的正确位置。

磁磁盘很早就支持直接在磁盘上进行命令排队(80 年代的 SCSI,2000 年代的 SATA)。因此,操作系统可以发出多个并行运行且可能乱序执行的命令,类似于 SSD。如果磁磁盘能够积累一个操作队列,让磁盘控制器随后可以调度读取和写入,以针对磁盘的几何结构进行优化,那么它们的性能也会得到提升。

这里有一个可视化,帮助我们看清随机磁带读取与随机磁盘读取之间的延迟差异。随机磁带读取通常需要数秒(我这里写了 1 秒,算是很宽容了),而磁盘寻道则接近 2 毫秒(千分之一秒)

尽管 HDD 相比磁带有所改进,但在某些场景下它们仍然“很慢”,尤其是随机读取和写入。下一个重大突破,也是目前事务型数据库最常见的存储格式,就是 SSD。

固态硬盘

固态存储,或称“闪存”存储,发明于 20 世纪 80 年代。即使在磁带和硬盘驱动器主导商业和消费级存储领域时,它也已经存在。由于技术限制和成本原因,直到 2000 年代它才成为消费级存储的主流。

SSD 相较于磁带和磁盘的优势在于,它们不依赖任何机械组件来读取数据。所有数据的读取、写入和擦除都是通过一种称为 NAND 闪存的特殊非易失性晶体管以电子方式完成的。这意味着每个 1 或 0 的读取或写入都无需移动任何物理组件,而是 100% 通过电信号完成。

SSD 被组织为一个或多个 target,每个 target 包含许多 block,每个 block 又包含一定数量的 page。SSD 在 page 级别读写数据,这意味着它们一次只能读取或写入完整的 page。在下面的 SSD 中,你可以看到读写操作通过控制器与 target 之间的连线(也称为 "trace")进行。

机械组件的移除降低了从发出请求到驱动器能够满足请求之间的延迟。不再需要等待某些东西旋转。

我们在可视化中展示的是小示例,以便于理解,但单个 SSD 能够存储数 TB 的数据。例如,假设每个 page 存储 4096 位数据(4k)。现在,假设每个 block 存储 16k 个 page,每个 target 存储 16k 个 block,而我们的设备有 8 个 target。这样算下来就是 4k * 16k * 16k * 8 = 8,796,093,022,208 位,即 8 TB。我们可以通过增加更多 target 或在每个 block 中容纳更多 page 来提高该驱动器的容量。

下面这个可视化帮助我们直观地看到 HDD 与 SSD 上随机读取延迟的差异。SSD 上的随机读取因型号而异,但最快可达到 16μs(μs = 微秒,即百万分之一秒)。

人们很容易认为,随着机械部件的移除,SSD 上数据的组织方式不再重要。既然我们不必等待东西旋转,就可以以完美的速度访问任何位置的任何数据,对吧?

还有其他因素会影响 SSD 上 IO 操作的性能。我们不会在这里全部涵盖,但我们将讨论其中两个:并行性和垃圾回收。

SSD 并行性

通常,每个 target 都有一条从控制单元到 target 的专用线路。这条线路负责处理读取和写入,每条线路一次只能传输一个 page。Page 在这些线路上的传输速度非常快,但仍然需要花费一小段时间。数据的组织方式和读写顺序对这些线路的使用效率有重大影响。

在下面的交互式 SSD 中,我们有 4 个 target 和一组排队的 8 个写操作。你可以点击 Time IO 按钮,看看当我们能够并行使用这些线路来写入这些 page 时会发生什么。

在这种情况下,我们将 8 个 page 分散写入 4 个 target。由于它们是分散的,我们能够利用并行性,在两个时间片中每次写入 4 个。

将其与另一种情况对比:SSD 将全部 8 个 page 写入同一个 target。SSD 只能利用单条数据线进行写入。同样,点击 Time IO 按钮查看时序。

注意这里只使用了一行,并且需要顺序写入。其他所有行都处于闲置状态。

这表明我们读写数据的顺序对性能有重要影响。许多软件工程师在日常工作中不需要考虑这一点,但设计像 MySQL 这类软件的人需要密切关注数据存储在什么结构中,以及数据在磁盘上如何布局。

SSD 垃圾回收

可以从 SSD 读取或写入的最小“块”是页(page)的大小。即使你只需要其中数据的一个子集,向驱动器发起请求时也必须以这个单位为粒度。

数据可以从一个页中读取任意多次。然而,写入则有些不同。一个页被写入后,在旧数据被显式擦除之前,不能覆盖写入新数据。棘手之处在于,单个页无法被擦除。当你需要擦除数据时,必须擦除整个块(block),之后其中的所有页才能被重新使用。

每个 SSD 都需要有一套内部算法来管理哪些页是空的、哪些正在使用、哪些是脏页(dirty page)。脏页是指已经被写入但数据不再需要、可以准备擦除的页。有时还需要重新组织数据,以便接纳新的写入流量。管理这些的算法被称为垃圾回收器(garbage collector)。

让我们通过另一个可视化来看看这会产生什么影响。在下面的 SSD 中,四个目标区域都在存储数据。其中一些数据是脏数据,用红色文字表示。我们想向这个 SSD 写入 5 页数据。如果我们对这段写入序列计时,SSD 可以顺利地将它们写入空闲页,无需额外的垃圾回收。第一个目标区域中有足够的未使用页。

现在假设我们有一个已经存有不同数据的驱动器,但我们想向它写入同样的 5 页数据。在这个驱动器中,我们只有 2 个未使用的页,但有一些脏页。为了写入 5 页数据,SSD 需要花一些时间进行垃圾回收,为新数据腾出空间。当尝试对另一段写入序列计时时,会发生一些垃圾回收来为数据腾出空间,从而拖慢写入速度。

在这种情况下,驱动器不得不将左上角目标区域中的两个非脏页移动到新位置。通过这样做,它能够使左上角目标区域中的所有页都变为脏页,从而可以安全地擦除这些数据。这为写入 5 个新页的数据腾出了空间。这些额外步骤显著降低了写入性能。

这表明驱动器上数据的组织方式会对性能产生影响。当 SSD 有大量读取、写入和删除操作时,最终可能因垃圾回收而导致性能下降。尽管你可能没有意识到,但繁忙的 SSD 会定期执行垃圾回收任务,这可能会拖慢其他操作。

这些只是 SSD 上数据排列方式影响其性能的众多原因中的两个。

云中的存储

从磁带、磁盘到固态硬盘的转变,使得持久化 IO 性能在过去几十年里急剧加速。然而,还有另一个现象导致了 IO 性能的额外转变:迁移到云端。

尽管在此之前已有公司提供云计算服务,但大规模迁移到云端的趋势在 2006 年 Amazon AWS 推出后获得了显著动力。自那时起,数以万计的公司将其应用服务器和数据库系统迁移到了 AWS 云以及 Google、Microsoft 等提供的其他类似服务上。

尽管这一趋势有许多优点,但也存在一些缺点。其中之一是服务器的持久性往往较低。用户在巨型数据中心内的任意硬件上租用(虚拟化)服务器。这些服务器可能因各种原因随时被关闭——硬件故障、硬件更换、网络断开等。在租用的云基础设施上构建平台时,计算机系统需要能够承受随时更频繁发生的故障。这一点,加上许多工程师对动态可扩展存储卷的需求,催生了一个新的子现象:存储与计算分离。

将存储与计算分离

传统上,大多数服务器、台式机、笔记本电脑、手机和其他计算设备的非易失性存储都是直接连接的。它们通过 SATA 线缆、PCIe 接口连接,甚至直接与 RAM、CPU 和其他组件集成在同一个 SOC 中。这对速度非常有利,但带来了以下挑战:

  • 如果服务器宕机,数据也会随之丢失。

  • 存储容量是固定的。

对于应用服务器而言,第 1 点和第 2 点通常不是大问题,因为它们在设计上就能很好地适应临时环境。如果一台服务器宕机,只需启动一台新的即可。它们通常也不需要太多存储,因为大部分操作都在内存中完成。

数据库则不同。如果服务器宕机,我们不希望丢失数据,而且数据量增长迅速,这意味着我们可能会触及存储上限。部分出于这个原因,许多云提供商允许你启动计算实例,并附加一个可通过网络单独配置的存储系统。换句话说,就是默认使用网络附加存储。

在 EC2 中创建新服务器时,默认通常是附加一个 EBS 网络存储卷。许多数据库服务,包括 Amazon RDS、Amazon Aurora、Google Cloud SQL 和 PlanetScale,都依赖这类将计算与存储通过网络分离的存储系统。这提供了一个很好的优势:存储卷可以随着数据的增长和缩减而动态调整大小。这也意味着如果服务器宕机,数据仍然安全,可以重新附加到另一台服务器上。然而,这种简单性是有代价的。

本地存储与网络存储

考虑以下简单配置。其中,我们有一台带有 CPU、RAM 和直接连接的 NVMe SSD 的服务器。NVMe SSD 是一种使用非易失性内存主机控制器接口规范的固态硬盘,具有极快的 IO 速度和出色的带宽。在这样的配置中,从 CPU 到内存(RAM)的往返大约需要 100 纳秒(一纳秒是十亿分之一秒)。从 CPU 到本地连接的 NVMe SSD 的往返大约需要 50,000 纳秒(50 微秒)。

这清楚地表明,为了更快的 IO 时间,最好将尽可能多的数据保留在内存中。然而,我们仍然需要磁盘,因为(A)内存更昂贵,(B)我们需要将数据存储在某个永久的地方。尽管这里看起来可能很慢,但本地连接的 NVMe SSD 已经是现代存储中最快的了。

让我们将其与网络附加存储卷(如 EBS)的速度进行比较。读写操作需要在数据中心内进行短暂的一次网络往返。往返时间显著更长,大约需要 250,000 纳秒(250 微秒,或 0.25 毫秒)。

使用同样先进的 SSD,现在完成单个读写请求所需的时间要长一个数量级。当我们有大量顺序 IO 时,这种负面影响可以减少,但无法消除。每次需要访问存储系统时,我们都会引入显著的延迟恶化。

云中网络附加存储的另一个问题在于 IOPS 限制。许多采用这种模式的云提供商,包括 AWS 和 Google Cloud,会限制你可以通过网络发送的 IO 操作数量。默认情况下,Amazon 上的 GP3 EBS 实例允许你每秒发送 3000 IOPS。这可以配置得更高,但需要额外费用。

较旧的 GP2 EBS 卷使用一个可以积累的 IOPS 池,以允许偶尔的突发。下面的可视化展示了这是如何工作的。请注意,这里的突发余额大小比实际情况小,以便更容易看到。

相反,如果你的存储直接附加到计算实例上,则不会对 IO 操作施加人为限制。你可以以硬件允许的最快速度进行读写。

尽管多年来我们在 IO 性能方面取得了许多进步,但这似乎是在朝着错误的方向迈出的一步。这种分离带来了一些不错的便利,但性能代价是什么?

我们如何在保持良好 IOPS 性能的同时,克服问题 1(数据持久性)和问题 2(驱动器可扩展性)?

问题 1 可以通过复制来克服。我们可以不依赖单台服务器存储所有数据,而是将数据复制到多台计算机上。一种常见的方式是让一台服务器充当主服务器,接收所有写请求。然后,2 台或更多额外服务器将数据复制到它们上面。数据存在于三个地方,丢失数据的可能性变得非常小。

让我们看一些具体数字。作为一个虚构的值,假设在某个月,服务器发生故障的概率为 1%。对于单台服务器,这意味着我们每个月有 1% 的概率丢失数据。对于任何严肃的商业用途来说,这都是不可接受的。然而,使用三台服务器时,这一概率降至 1% × 1% × 1% = 0.0001%(百万分之一)。在 PlanetScale,保护实际上比这还要强得多,因为我们会自动检测并替换集群中故障的节点。我们会对你数据库中的数据进行频繁且可靠的备份,以提供额外保护。

问题 2 可以解决,尽管在使用直接附加的 SSD 时需要更多手动干预。我们需要确保在磁盘接近容量限制时进行监控并收到警报,然后拥有在需要时轻松增加容量的工具。有了这样的功能,我们就可以实现数据持久性、可扩展性和极快的性能。这正是 PlanetScale 通过 Metal 所构建的。

解决方案:Metal

Planetscale 刚刚发布了 Metal,这是针对该问题的行业领先解决方案。

使用 Metal,你可以获得一个功能完备的数据库集群(Vitess 或 Postgres),每个数据库实例都运行在直连的 NVMe SSD 驱动器上。每个 Metal 集群默认配备一个主节点和两个副本,以实现极高的数据持久性。当存储达到上限时,只需点击几下按钮,即可将服务器扩容为更大容量的驱动器。在幕后,我们负责启动新节点并将数据从旧实例迁移到新实例,且实现零停机。

也许最重要的是,使用 Metal 数据库时,IOPS 没有人为上限。你可以以极低延迟执行 IO 操作,并且可以随心所欲地高强度使用,而不会被限流,也无需为你常用的云服务商上昂贵的 IOPS 等级付费。

如果你追求极致的性能和可扩展性,今天就试试 Metal 吧。


转载声明:本文为转载整理,原文版权归原作者及原站点所有。

原文来源:PlanetScale Blog

原创地址:https://planetscale.com/blog/io-devices-and-latency

原文作者:PlanetScale Blog;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2022-11-21

  • 博文量
    1090
  • 访问量
    546942