不久前,家庭中唯一的流媒体来源是通过使用机顶盒 (STB) 的有线电视服务或通过天线进行无线广播。大多数人没有意识到的是,它们都基于相同的原理:内容是持续流式传输的,天线接收无线频率,而机顶盒接收同轴电缆上的频率。
然后互联网赶上了——现在大多数内容都是通过互联网流式传输的。虽然不同报告中互联网流量中流媒体内容所占的具体百分比有所不同,但它们都同意两点:流媒体内容占互联网流量的大部分,并且这一比例逐年上升。
什么是首字节时间 (TTFB) 以及为什么它对互联网视频很重要?
与无线或有线流媒体不同,无线或有线流媒体是持续广播到被授权接收内容的设备,而对于互联网视频,用户的设备需要请求内容,并且只有在握手和授权完成后,视频才会开始流式传输。
首字节时间是指视频流的第一个字节在用户设备上可用所需的时间。更实际地说,就是用户点击播放流媒体视频到视频实际开始播放所需的时间。
在没有竞争的情况下,用户愿意等待长达 10-15 秒才能开始通过互联网流式传输内容。现在,新鲜感已过,市场竞争激烈,延迟超过几秒(甚至任何延迟)都可能意味着客户流失与留存之间的差异。
服务器端面临的挑战
流媒体提供商面临着多项重大挑战。虽然边缘缓存和 CDN 通过缓存一些更常见的内容来改善用户体验,但它仍然不是所有内容,并且仍然存在从源服务器获取内容的问题。
他们还必须处理多种不同的用例:长期驻留的视频点播 (VOD) 资产(例如电影、节目等)、短期驻留的 VOD 资产(例如直播体育赛事剪辑等)和 DVR 资产(用户决定“存储”的视频)。
传统的 SAN 和 NAS 解决方案非常适合数据库、文件共享等事务数据,但并非为流媒体内容而设计。在协议和提供扩展性和高可用性所需的许多软件层之间,它们是流媒体数据的错误选择。
由于许多对象存储是从供应商的文件系统架构(而非真正的对象存储方法)改编而来的,因此它们需要外部元数据数据库。这由于多种原因而存在问题,这些问题已在此帖子中详细介绍。其中之一是它消除了严格一致性的可能性,因为对象和元数据是分开写入的,导致系统容易发生数据损坏。
单独的元数据存储还会由于额外的查找调用开销以及需要分别扩展对象存储和元数据存储而导致巨大的性能和可扩展性问题。
内容寻址存储 (CAS) 和传统对象存储专为归档/辅助存储用例而设计。这些类型存储的突出示例使用 Cassandra 作为其元数据存储,这会损害性能和一致性。我们之前写过这方面内容。
当资产周转率很高(即视频经常添加和删除)时,可扩展性问题会变得更加严重。
MinIO - 数据的最短路径
在 MinIO,我们从头开始构建我们的对象存储以解决这些问题。
让我们一起了解为确保应用程序能够以尽可能短的路径访问它们尝试访问的数据而做出的架构决策。
Go 和 Go 汇编
MinIO 编写为单进程轻量级绿色线程(也称为 Goroutines),专为大规模并发操作而设计。
SIMD 优化
现代 CPU 的功能足以消除对外部加速器或定制 ASIC 的需求。现代 CPU 最重要的功能之一是能够执行所谓的单指令多数据 (SIMD) 指令。MinIO 利用了 Intel、AMD、ARM 和 PowerPC CPU 中的这些功能。
结果是,通常占用大量 CPU 的操作(如擦除编码、加密、校验和验证等)现在变得快速且免费。无需外部加速器(例如 GPU),因为瓶颈不再位于计算层,而是取决于 I/O 子系统(网络、驱动器和系统总线)。
不是传统文件系统的网关
MinIO 是专门构建的对象存储。它不仅仅是 SAN 或 NAS 等标准文件系统的网关或 API 代理。
最重要的是,MinIO 利用直接连接存储,即连接到计算机的驱动器。访问视频资产不需要额外的网络或软件层。本地 PCIe 总线比任何网络访问驱动器都快。
简单
MinIO 软件栈中没有不必要或额外的软件层。
具有原生 S3 API 接口的微服务架构只是一个带有处理程序的 Web 服务器。这种简单性使其成为一个强大且高性能的平台。
如前所述,外部元数据存储是高性能和可扩展对象存储的最大瓶颈之一。
MinIO 对对象和元数据都具有严格的一致性,因为它们作为单个操作一起写入。不仅保证了在返回 200 OK 时写入对象和元数据,而且也不再存在单独的元数据存储的瓶颈。
使用对象写入元数据消除了由资产高周转率引起的任何潜在问题,在资产高周转率中,大量删除会对元数据存储造成巨大挑战。
MinIO 以压缩的 msgpack 格式写入元数据,以减少存储空间并提高检索速度。
无全局锁
创建真正分布式系统最具挑战性的部分之一是,几乎所有系统都需要全局锁。
MinIO 通过确保锁粒度且处于每个对象级别来完全消除了对全局锁的需求。这样,对一个对象的操作不会影响任何其他对象。我们的版本控制机制确保没有资源争用,因此不需要全局锁。
DirectIO
内核缓存对延迟和内存管理造成了巨大影响。MinIO 绕过内核缓存以优化流媒体性能以及弹性和持久性。
擦除编码
最终的 MinIO 设计模式,可以在大规模下实现低 TTFB,就是擦除编码。除了节点的无状态特性外,它不仅以合理的成本提供了对驱动器和节点故障的高度容错能力,而且由于元数据与对象的每个分片一起写入,因此可以从任何驱动器有效地获取整个对象。
流媒体工作负载优化
上一节详细介绍了 MinIO 对任何需要对象存储的工作负载的优势。MinIO 还针对流媒体工作负载进行了优化。
原生流媒体协议
HTTP(S) 旨在直接流式传输到最终用户。MinIO 原生支持 S3 接口,HTTP 协议非常适合流式传输视频。
分段上传
视频通常是大型文件。MinIO 允许将这些视频文件分解成一系列部分,然后可以上传。由于能够并行上传部分,这极大地提高了吞吐量。此外,较小的部分允许从网络问题中快速恢复,能够暂停和恢复一段时间内部分的上传等等。
流媒体范围获取
为了对视频流进行细粒度控制——例如,从视频中的特定点继续或提供剪辑——重要的是,整个对象不需要首先加载到内存中,然后对该对象执行操作。这种低效率会大大增加 TTFB 和使用的内存量。MinIO 支持范围获取,其中部分对象可作为流提供。应用程序能够提供偏移量、所需长度甚至对象的特定版本。
流媒体块支持
为了确保在流式传输时可以有效地读取对象,MinIO 在每个块(而不仅仅是在对象级别)添加校验和。这消除了在开始流式传输之前加载整个对象的需要。这也显着减少了内存使用,因为整个对象不必加载到内存中。
校验和也使用 Highway Hash 算法计算,该算法比更常用的 CRC32 方法效率更高。更重要的是,CRC32 容易发生哈希冲突,因此在防止静默数据损坏方面不够可靠。MinIO 优化了 Highway Hash,以实现接近内存速度的哈希,同时保留哈希强度。
对象分片作为擦除编码机制的一部分确定性地放置。这允许读取并行,这在 RAID 或 NAS 设置中是不可能的。同样,由于每个分片都包含完整的元数据,因此它可以获取整个对象。
基准测试结果
我们进行了一系列测试,以展示流媒体工作负载的性能一致性。
测试配置
测试在一个 8 节点的集群上进行。请注意,这些是较旧的系统,NVMe 驱动器的顺序读取速度仅约为 2GB/s。较新的 NVMe 驱动器在 PCIe 3.0 上显示 3.5GB/s 到 PCIe 4.0 上的 8GB/s。PCIe 5.0 为 12 GB/s,但目前价格过高。这意味着这些数字只会越来越好。
每个节点包含
- 内存:384GB
- 网络:100Gbps
- 10 个 1TB NVMe 驱动器
结果 #1:即使在高并发率下,TTFB 也非常低
我们运行的第一个测试测量了高并发率对 TTFB 的影响。选择 1 MB 的对象大小是因为流媒体提供商使用它来实现更好的 CDN 缓存。
第 75 和第 90 百分位的结果以毫秒为单位
对象大小 | 并发性 | 第 75 百分位(毫秒) | 第 90 百分位(毫秒) |
1 MiB | 160 | 26 | 35 |
1 MiB | 240 | 35 | 46 |
1 MiB | 320 | 45 | 56 |
1 MiB | 480 | 72 | 90 |
1 MiB | 640 | 98 | 118 |
1 MiB | 720 | 105 | 126 |
1 MiB | 800 | 118 | 142 |
1 MiB | 960 | 137 | 163 |
1 MiB | 1600 | 205 | 241 |
1 MiB | 2400 | 289 | 339 |
1 MiB | 4000 | 449 | 525 |

MinIO 在并发负载下提供了极其一致的性能。在 4000 个并发请求下,第 75 百分位的 TTFB 保持在 0.5 秒以下。
结果 #2:偏移读取的 TTFB 与给定并发性的对象大小无关
此测试评估了从不同大小的对象的不同偏移量读取的影响。这里使用更大的文件来确保搜索值足够高以具有意义。
第 75 和第 90 百分位的结果以毫秒为单位
并发性 | 对象大小 | 偏移量 | 第 75 百分位(毫秒) | 第 90 百分位(毫秒) |
160 | 64 MiB | 10B -> 100KiB | 14 | 20 |
160 | 64 MiB | 100KiB -> 1MiB | 14 | 19 |
160 | 64 MiB | 1MiB -> 10MiB | 13 | 19 |
160 | 64 MiB | 10MiB -> 64MiB | 15 | 21 |
160 | 100 MiB | 10B -> 100KiB | 13 | 20 |
160 | 100 MiB | 100KiB -> 10MiB | 13 | 19 |
160 | 100 MiB | 10MiB -> 100MiB | 14 | 20 |

结果表明,对于固定的并发性,偏移读取的 TTFB 在对象大小之间是一致的。
结果 #3:偏移读取的 TTFB 对于给定的并发性是一致的
下一个测试测量了从具有不同递增并发性的对象的不同偏移量读取的影响。同样,这里使用更大的文件来确保搜索值足够高以具有意义。
第 75 和第 90 百分位的结果以毫秒为单位
对象大小 | 并发性 | 偏移量 | 第 75 百分位(毫秒) | 第 90 百分位(毫秒) |
64 MiB | 160 | 10B -> 100KiB | 14 | 20 |
64 MiB | 160 | 100KiB -> 1MiB | 14 | 19 |
64 MiB | 160 | 1MiB -> 10MiB | 13 | 19 |
64 MiB | 160 | 10MiB -> 64MiB | 15 | 21 |
64 MiB | 640 | 10B -> 100KiB | 131 | 158 |
64 MiB | 640 | 100KiB -> 1MiB | 124 | 144 |
64 MiB | 640 | 1MiB -> 10MiB | 124 | 144 |
64 MiB | 640 | 10MiB -> 64MiB | 125 | 146 |
64 MiB | 800 | 10B -> 100KiB | 174 | 216 |
64 MiB | 800 | 100KiB -> 1MiB | 169 | 204 |
64 MiB | 800 | 1MiB -> 10MiB | 170 | 206 |

结果表明,对于给定的并发性,TTFB 与正在从中读取的对象中的偏移量无关。
不要仅仅相信我们的说法 - 自己进行基准测试。
随着互联网流量的大部分成为流媒体,TTFB 已成为衡量性能的重要指标。众所周知,缓慢的 TTFB 会降低客户体验并可能导致大量流失。正如这篇博文所证明的那样,从 MinIO 提供的对象无论大小、偏移量和并发性如何,都具有较低的 TTFB。
与我们联系 (hello@min.io) 或下载 MinIO 并亲自尝试一下。您将发现为什么世界上一些最大的流媒体公司将其基础设施标准化到 MinIO 上。