本文为学习目的的个人翻译,译文及后文「译者总结」仅供参考。
原文链接:How Netflix Live Streams to 100 Million Devices in 60 Seconds。
版权归原作者或原刊登方所有。本文为非官方译本;如有不妥,请联系删除。
Netflix Live Origin 是一台自研服务器,位于云端直播流媒体管线与 Open Connect——也就是 Netflix 的内容分发网络(CDN)——之间。它就像一个质量控制检查点,决定哪些视频分片会被发送给全球数百万观众。
当 Netflix 最初引入直播能力时,他们需要一个能够处理实时视频分发独特挑战的系统。与内容会提前准备好的点播视频(VOD)不同,直播运行在严格的时间约束之下。每个视频分片都必须在几秒钟内完成编码、封装并交付到观众手中。Live Origin 正是为了承接这些要求而专门设计的。
在这篇文章中,我们将看看这个系统的架构,以及 Netflix 在构建它时遇到的挑战。
免责声明:本文基于 Netflix Engineering Team 公开分享的细节整理而成。如果你发现有任何不准确之处,欢迎指出。
系统如何工作
Live Origin 以多租户微服务的形式运行在 Amazon EC2 实例上。它的通信模型相当直接:
- 负责准备视频分片以供分发的 Packager,会通过 HTTP PUT 请求把这些分片发送到 Origin。
- Open Connect 节点则通过 HTTP GET 请求取回这些分片。PUT 请求使用的 URL 与 GET 请求使用的 URL 相同,从而形成一种简单的存取模式。
见下图:

Netflix 做了几个架构决策,这些决策塑造了 Live Origin 的工作方式。
- 第一,他们通过冗余的区域级直播流媒体管线来实现可靠性。Netflix 不是依赖单一编码管线,而是同时运行两条彼此独立的管线。每条管线运行在不同的云区域,并拥有各自独立的编码器、打包器以及视频输入源。
- 第二,Netflix 采用了带有 segment template 和固定 segment duration 的 manifest 设计。它们不是不断更新 manifest 文件去列出当前可用的分片,而是使用一种可预测的模板,其中每个分片都有固定的 2 秒时长。这样的设计让 Origin 可以准确预测某个分片应在何时发布。
由于直播视频源本身不可预测,再加上实时发布时限非常严格,直播流中不可避免地会出现缺陷。常见问题包括:视频帧或音频采样缺失导致的短分片、整个分片完全缺失,以及解码时间戳错误导致的时间连续性中断。
同时运行两条独立管线,会大幅降低两条管线在同一时间都产出有缺陷分片的概率。因为这两条管线使用的是不同的云区域、不同的编码器和不同的视频源,所以当一条管线产生坏分片时,另一条通常仍会产生好分片。
多管线感知与智能选择
Live Origin 利用自己处在分发路径中的位置,做出智能决策。当 Open Connect 请求某个分片时,Origin 会按预先设定的顺序检查来自两条管线的候选分片,并选择第一个有效的分片。
为了检测缺陷,Packager 会执行轻量级媒体检查,并在向 Origin 发布分片时,把缺陷信息作为元数据一并附上。在极少数两条管线都产出缺陷分片的情况下,这些缺陷信息也会继续向下游传递,以便客户端适当地处理错误。
面向 Open Connect 的优化
当 Live 项目启动时,Open Connect 已经针对 VOD 分发做了高度优化。Netflix 花了很多年去调优 nginx(一个 Web 服务器)以及底层操作系统,以适应这类场景。与传统 CDN 按需填充缓存不同,Open Connect 会把 VOD 资源预先放置到精心挑选的服务器上,这些服务器被称为 Open Connect Appliances(OCA)。
直播并不能自然地套入这套模型,因此 Netflix 扩展了 nginx 的 proxy-caching 功能。他们做了多项优化,以减少不必要的流量并提升性能。
Open Connect 节点会收到与客户端相同的 segment template。借助这些模板信息,OCA 可以在任意时刻判断某个事件下哪些分片编号范围是合法的。这让它们可以立刻拒绝那些超出范围的分片请求,从而阻止无意义的请求继续穿过网络抵达 Origin。
当一个分片尚未可用,而 Origin 收到对它的请求时,Origin 会返回 404 状态码(File Not Found),同时附带一个过期策略。Open Connect 可以把这个 404 缓存到该分片即将发布前的那一刻,从而避免反复发起失败请求。
Netflix 针对 live edge,也就是流中最新的那部分内容,实现了一项巧妙优化。当某个请求到达时,如果它请求的是即将发布的下一个分片,Origin 不会再返回一个会沿着网络一路传回客户端的 404,而是会把这个请求挂住。等分片一发布,Origin 就立刻响应这个等待中的请求。这样能显著减少那些稍微提前到达的请求所带来的网络流量。
为了支持这个功能,Netflix 还给 nginx 增加了毫秒粒度的缓存。标准 HTTP Cache Control 只能以秒为单位工作,而当分片每 2 秒生成一次时,这种粒度就过于粗糙了。
通过 HTTP Header 传递流媒体元数据
Netflix 使用自定义 HTTP Header,以一种高度可扩展的方式传递流媒体事件信息。直播流媒体管线会向 Origin 提供通知,Origin 再把这些通知插入到当时刻生成的分片响应头中。这些 Header 是累积性的,也就是说,它们会持续附着到后续分片上。
每当一个分片到达某个 OCA 时,通知信息就会从响应头中提取出来,并以 event ID 为键存入内存。当 OCA 把某个分片发送给客户端时,它会把最新的通知数据附在响应中。这个系统保证了无论观众当前播放到流中的哪个位置,都能收到最新的通知数据。即便某次响应没有提供新分片,这些通知也仍然可以通过该响应传递给客户端。
这种方式让 Netflix 能够高效地把广告开始、内容提醒或直播事件更新等信息传递给数百万设备,而且不依赖于观众当前的播放位置。
缓存失效与 Origin Masking
Netflix 构建了一套失效系统,它可以通过修改缓存键所使用的版本号,刷新某个事件对应的全部内容。这在活动开始前的测试阶段尤其有用,因为它能让网络在每次测试之间都回到干净状态。
Live Origin 发布的每个分片都包含了元数据,说明它是由哪条编码管线生成、来自哪个区域。增强后的失效系统会把这些变体因素也考虑进去。Netflix 可以只失效某一段分片编号范围,但前提是它们来自特定编码器,或者来自某个特定区域中的某个特定编码器。
结合这套缓存失效能力,Live Origin 还支持选择性编码管线屏蔽(selective encoding pipeline masking)。这个功能允许运维团队在向 Open Connect 提供内容时,排除某一条特定管线中的问题分片。当直播事件中检测到坏分片时,这套系统就可以把这些有问题的内容隐藏起来,从而保护数百万观众。这个能力在 DVR 回看窗口中尤其重要,因为观众可能会把时间轴拖回到那段有问题的内容。
存储架构的演进
Netflix 最初为 Live Origin 使用的是 AWS S3 存储,这和它们的 VOD 基础设施类似。在低流量事件中,这个方案表现良好;但随着规模扩大,他们发现直播有一套与点播内容截然不同的需求。
虽然 S3 达到了其承诺的可用性水平,但直播事件天然存在严格的 2 秒重试预算,因此任何延迟都会成为问题。在直播里,每一次写入都是关键且有时限的。它所要求的,更像是一个全球化、低延迟、高可用数据库,而不是对象存储。
Netflix 为新的存储系统提出了五项关键要求。
- 第一,他们需要在单个 AWS 区域内实现极高的写可用性,并能以低延迟复制到其他区域。任何超过 500 毫秒的失败写操作都被视为一个 bug。
- 第二,系统必须支持高写吞吐,能够在区域之间复制数百 MB 的数据。
- 第三,它必须高效支持大写入,这些写入会在同一分区中累积出数千个键。
- 第四,他们需要同一区域内的强一致性,以把读取延迟压到 1 秒以内。
- 第五,在 Open Connect 出现最坏边缘情况时,系统可能需要承受 GB 级的读吞吐,而且不能影响写路径。
Netflix 以前构建过一个键值存储抽象层(Key-Value Storage Abstraction),它基于 Apache Cassandra,为大值提供分块存储。这个抽象层最初是为云端游戏存档设计的,但 Live 场景会在写可用性、累计分区大小和读吞吐方面把它逼到极限。
它的解决方案是把大负载拆成多个块,每个块都可以独立重试。再结合 Apache Cassandra 的 local-quorum 一致性模型——即便整个可用区故障也仍能保持写可用——以及面向写优化的 Log-Structured Merge Tree 存储引擎,Netflix 最终满足了前四项要求。
性能提升也相当扎实:中位延迟从 113 毫秒降到 25 毫秒,99 分位延迟从 267 毫秒降到 129 毫秒。新方案更贵,但降低成本并不是首要目标。
不过,要处理 Origin Storm 这种失败场景,还需要额外工作。在这种情况下,数十个 Open Connect 顶层缓存可能会同时请求多个大型视频分片。测算结果显示,最坏情况下读吞吐可能达到 100 Gbps 甚至更高。
Netflix 可以直接从 Apache Cassandra 以网络线速响应这些读取请求,但他们观察到并发写入会出现不可接受的性能退化。为了解决这个问题,他们引入了基于 EVCache 的 write-through cache。EVCache 是 Netflix 基于 Memcached 的分布式缓存系统。这样一来,几乎所有读取都可以由高度可扩展的缓存承担,从而在不影响写路径的情况下,把吞吐提升到 200 Gbps 甚至更高。
最终架构中,Live Origin 会对 KeyValue 进行读写;KeyValue 会把 write-through cache 写入 EVCache,并实现一个分块协议,把大值分散存储到 Apache Cassandra 集群中。几乎全部读负载都由缓存承担,只有缓存未命中才会落到存储层。过去一年多里,这套组合已经成功满足了 Live Origin 的高强度需求。
可扩展性与请求优先级
Netflix 的直播平台需要为每场直播事件处理大量、且类型多样的 stream rendition。这种复杂性来自它必须同时支持多种视频编码格式及多个质量档位、不同语言和格式的多条音频轨,以及带广告和不带广告等不同内容版本。在 2024 年 Tyson vs. Paul 那场比赛期间,Netflix 观察到了历史峰值:6500 万并发流。
Netflix 选择构建一个高度可扩展的 origin,而不是依赖传统 origin shield,因为这样能更好地控制缓存一致性,同时也能简化系统架构。Live Origin 会直接连接分布在多个站点、按地理分布的顶层 Open Connect 节点。为了尽量减轻 origin 的负载,在每个站点上,每个 stream rendition 只有指定节点可以直接从 origin 填充缓存。
见下图:

尽管 origin 服务本身可以通过增加 EC2 实例水平扩展,但其他系统资源,比如存储平台容量和骨干带宽,并不能自动扩展。而且,并不是所有发往 live origin 的请求都有同样的重要性。Origin 写入最关键,因为写失败会直接影响流媒体管线;live edge 上的 Origin 读取也很关键,因为失败会影响绝大多数客户端;而 DVR 模式下的 Origin 读取则没那么关键,因为失败只会影响那些正在回看的客户端。
Netflix 实现了完整的发布隔离(publishing isolation),以保护对延迟和失败都非常敏感的 origin 写入路径。Origin 会把发布流量和 CDN 流量放在独立的 EC2 栈上;存储抽象层会为读和写分别使用不同集群;而存储层本身也把读路径(EVCache)与写路径(Cassandra)分离开来。这种完整路径隔离使发布流量与分发流量能够独立扩展,并防止 CDN 流量激增影响发布性能。
当底层系统承受压力时,Live Origin 会基于优先级实施限流。这种做法可以保证用户影响更大的请求优先成功,而让用户影响较小的请求在高负载时允许失败。在存储平台负载较高时,live edge 流量会优先于 DVR 流量。判断依据来自可预测的 segment template,它会被缓存在 origin 节点的内存中,因此无需访问数据存储就能完成优先级决策——这在数据存储承压时尤其重要。
为了缓解流量激增,Netflix 还把 TTL cache control 与优先级限流结合起来使用。当低优先级流量受影响时,Origin 会通过设置 max-age 指令并返回 HTTP 503 错误码,通知 Open Connect 把相同请求缓存 5 秒。这个策略通过阻止 5 秒窗口内的重复请求,有效抑制了流量洪峰。
处理 404 风暴
发布隔离和优先级限流,已经足以保护 live origin 免受 DVR 流量风暴冲击。然而,由对不存在分片的请求所引发的流量风暴,还带来了额外挑战,也带来了进一步优化的机会。
Live Origin 以分层方式组织元数据:事件(event)、stream rendition 和 segment。分片发布模板维护在 stream rendition 这一层。这种层次化组织方式,使 origin 可以利用高度可缓存的事件级与 rendition 级元数据,提前拒绝请求,从而避免不必要地去查询 segment 级元数据。
它的工作过程如下:
- 如果事件未知,请求会以 404 错误被拒绝。
- 如果事件存在,但分片请求的时间点与预期发布时间不匹配,请求会以 404 被拒绝,同时附带一个与预期发布时间一致的 cache control TTL。
- 如果事件存在,但请求的分片根本没有被生成,或者已经错过重试截止时间,请求会以 410(Gone)错误被拒绝,这会明确告诉客户端不要再继续请求。
在存储层,元数据与媒体数据分开存储在 control plane datastore 中。与媒体数据存储不同,control plane datastore 不使用分布式缓存,以避免缓存不一致。对于 live origin 实例而言,事件级和 rendition 级元数据在使用内存缓存时能获得很高的命中率。在针对不存在分片的流量风暴中,control plane 的缓存命中率很容易超过 90%。
通过对元数据使用内存缓存,Live Origin 可以在不对数据存储造成压力的情况下有效应对 404 风暴。这种元数据缓存与存储系统中的分布式媒体缓存相互补充,共同构成了一套完整的流量洪峰防护方案。
结论
Netflix Live Origin 是一套专门为超大规模直播场景打造的复杂系统。
通过冗余管线、智能分片选择、优化后的缓存策略、优先级化请求处理,以及定制化存储架构,Netflix 构建出了一套可靠基础设施,能够把直播事件交付给全球数百万并发观众。
这套系统成功平衡了写入可靠性、读取可扩展性与运维灵活性之间相互竞争的要求,并在 Tyson vs. Paul 这样的重大事件中证明了自身有效性——那场直播曾达到 6500 万并发流。
参考资料
译者总结
这篇文章的主线,是解释 Netflix 如何围绕直播场景重新设计 origin,而不是简单把 VOD 架构直接拿来复用。文中从 Live Origin 的定位讲起,再逐步展开到多管线选择、Open Connect 优化、元数据传递、缓存失效、存储演进和限流策略。
其中一个关键点是,Netflix 把直播问题拆成了多个不同层面的可靠性问题:分片质量问题由双管线和缺陷元数据来缓解,请求洪峰问题由缓存、挂起请求、优先级限流和 404/410 策略来处理,而读写路径冲突则通过 EVCache 与 Cassandra 的分层设计来隔离。
文中提到的很多优化都建立在“可预测”这一前提上,例如固定 2 秒分片时长、segment template、事件与 rendition 层级元数据等。正因为发布时间和合法请求范围可预测,Origin 与 Open Connect 才能提前做出缓存、拒绝和优先级决策。
原文含推广段落,已略。文中数据如 6500 万并发流、100 Gbps 以上最坏读吞吐、200 Gbps 以上缓存读吞吐等,都服务于同一个结论:这套系统不是单点优化,而是一整套围绕直播时延、可靠性和规模约束共同设计出来的架构。