业界 | 每天1.4亿小时观看时长,Netflix怎样存储这些时间序列数据?

简介:

网络互联设备的增长带来了大量易于访问的时间序列数据。越来越多的公司对挖掘这些数据感兴趣,从而获取了有价值的信息并做出了相应的数据决策。

近几年技术的进步提高了收集,存储和分析时间序列数据的效率,同时也刺激了人们对这些数据的消费欲望。然而,这种时间序列的爆炸式增长,可能会破坏大多数初始时间序列数据的体系结构。

Netflix作为一家以数据为驱导的公司,对这些挑战并不陌生,多年来致力于寻找如何管理日益增长的数据。我们将分享Netflix如何通过多次扩展来解决时间序列数据的存储架构问题。

时间序列数据——会员观看记录

Netflix会员每天观看超过1.4亿小时的内容。而每个会员在点击标题时会产生几个数据点,这些数据点将被作为观看记录进行存储。Netflix通过分析这些观看数据,为每位会员提供了实时准确的标签和个性化推荐服务,如这些帖子中所述:

8481c8f592b7f349aa84a1de5c171db681516edf如何判断你在观看一个节目?

https://medium.com/netflix-techblog/netflixs-viewing-data-how-we-know-where-you-are-in-house-of-cards-608dd61077da

8481c8f592b7f349aa84a1de5c171db681516edf 帮助你继续观看Netflix的节目。

https://medium.com/netflix-techblog/to-be-continued-helping-you-find-shows-to-continue-watching-on-7c0d8ee4dab6

从以下3个维度累积历史观看记录:

8481c8f592b7f349aa84a1de5c171db681516edf 随着时间的推移,每个会员的更多观看记录数据将被存储。
8481c8f592b7f349aa84a1de5c171db681516edf 随着会员数量的增长,更多会员的观看记录数据会被存储。
8481c8f592b7f349aa84a1de5c171db681516edf 随着会员每月观看时间的累积,每个会员的更多观看记录将被存储。

过去十年的发展,Netflix已经在全球拥有1亿名会员,其观看记录的数据亦是大幅增加。在本篇博客中,我们将重点讨论如何应对存储观看历史数据带来的巨大挑战。

从简单的开始

观看记录的第一版原生云存储架构使用Cassandra的理由如下:

8481c8f592b7f349aa84a1de5c171db681516edf Cassandra对时间序列数据建模提供了很好的支持,其中每行都有动态的列数。
8481c8f592b7f349aa84a1de5c171db681516edf 观看记录数据的读写速度比约为9:1。由于Cassandra的写入效率非常高,因此Cassandra非常适合频繁写入操作的工作。
8481c8f592b7f349aa84a1de5c171db681516edf 根据CAP定理,团队更倾向于最终的一致性。Cassandra支持通过调整一致性进行权衡。

在最初的方法中,每个成员的观看历史记录都存储在Cassandra中,并使用行键存储在一行中:CustomerId。这种水平分区的方式能够随着会员数量的增长而有效扩展,并且使得浏览会员的整个观看记录的常见用例变得简单、高效。

然而随着会员数量的增加,更重要的是,每个会员的流量越来越多,行数和整体数据量也越来越多。随着时间的推移,这导致了昂贵的操作成本,对于读写具有海量观看记录的会员数据而言性能较差。

下图说明了初始数据模型的读写流程:

b7a5b9c44b8f1460d99aaa77593accae00dc929d

图1:单个图表数据模型

写流程

当会员点击播放时,一条观看记录将作为新的列插入。点击暂停或停止后,则该观看记录被更新。可见对于单列的写入是迅速和高效的。

读流程

通过整行读取来检索一个会员的所有观看记录:当每个会员的记录数很少时,读取效率很高。但是随着一个会员点击更多标题产生更多的观看记录。此时读取具有大量列的行数据会给Cassandra带来额外的压力,并造成一定的读取延迟。

通过时间范围查询读取会员数据的时间片:将导致了与上面的性能不一致,这取决于在指定的时间范围内查看记录的数量。

通过分页整行读取大量观看记录:这对于Cassandra来说是好的,因为它并不需要等待所有的数据返回就可以加载。同时也避免了客户端超时。然而,随着观看记录数量的增加,整行读取的总延迟增加了。

放缓原因

让我们来看看Cassandra的一些内部实现,以了解为什么我们最初简单设计的性能缓慢。随着数据的增长,SSTable的数量相应增加。

由于只有最近的数据在内存中,所以在很多情况下,必须同时读取memtables和SSTable才能检索观看记录。这样就造成了读取延迟。同样,随着数据量的增加,压缩需要更多的IO和时间。由于行越来越宽,读修复和全列修复因此变得更加缓慢。

缓存层

虽说Cassandra在观看记录数据写入方面表现很好,但仍有必要改进读取延迟。为了优化读取延迟,需要以牺牲写入路径上的工作量为代价,我们通过在Cassandra存储之前增加内存分片缓存层(EVCache)来实现。

缓存是一种简单的键值对存储,键是CustomerId,值是观看记录数据的压缩二进制表示。每次写入Cassandra都会发生额外的缓存查找,并在缓存命中时将新数据与现有值合并。

读取观看记录首先由缓存提供服务。在高速缓存未命中时,再从Cassandra读取条目,压缩并插入高速缓存。

多年来随着缓存层的增加,这种单一的Cassandra表格存储方法表现良好。基于CustomerId的分区在Cassandra集群中可扩展性亦较好。

直到2012年,观看记录Cassandra集群成为Netflix最大的Cassandra集群之一。为进一步扩展,团队决定将集群规模扩大一倍。

这就意味着Netflix要冒险进入使用Cassandra的未知领域。与此同时,伴随着Netflix业务的快速增长,包括不断增加的国际会员数和即将投入的原创内容。

重新设计:实时和压缩存储方法

显然,需要采取不同的方法进行扩展来应对未来5年的预期增长。团队分析了数据特征和使用模式,重新设计了观看记录存储方式并实现了两个主要目标:

8481c8f592b7f349aa84a1de5c171db681516edf 较小的存储空间
8481c8f592b7f349aa84a1de5c171db681516edf 每个会员的观看记录增长与读写性能保持一致

对于每个会员,观看记录数据被分成两个集合:

8481c8f592b7f349aa84a1de5c171db681516edf 实时或近期观看记录(LiveVH):频繁更新的最近观看记录数量较少。这样的数据以非压缩形式存储,如上面简单的设计中所述。
8481c8f592b7f349aa84a1de5c171db681516edf 压缩或存档观看历史记录(CompressedVH):大量较早的观看记录很少更新。 这样的数据将被压缩以减少存储空间。压缩的观看历史记录存储在每行键的单个列中。

LiveVH和CompressedVH存储在不同的表格中,并通过不同的调整以获得更好的性能。由于LiveVH的频繁更新和拥有少量的观看记录,因此压缩需频繁进行,且保证gc_grace_seconds足够小以减少SSTables数量和数据大小。

只读修复和全列修复频繁进行保证数据的一致性。由于对CompressedVH的更新很少,因此手动和不频繁的全面压缩足以减少SSTables的数量。在不频繁更新期间检查数据的一致性。这样做消除了读修复以及全列维修的需要。

使用与前面所述相同的方法将新观看记录写入LiveVH。

写流程

使用与前面所述相同的方法将新观看记录写入LiveVH。

读流程

为了从新设计中获益,观看历史记录的API已更新,可以选择读取最近的或完整的数据:

8481c8f592b7f349aa84a1de5c171db681516edf 最近观看记录:对于大多数的用例,只需从LiveVH中读取数据,通过限制数据大小降低延迟。

8481c8f592b7f349aa84a1de5c171db681516edf完整的观看记录:作为LiveVH和CompressedVH的并行读取实现。由于数据压缩和CompressedVH的列较少,因此通过读取较少的数据就可以显著加速读取。

CompressedVH更新流程

当从LiveVH中读取观看历史记录时,如果记录数量超过可配置的阈值,那么最近的观看记录就被汇总一次,压缩并通过后台任务存储在CompressedVH中。然后使用行键(行关键字):CustomerId将数据存储在新行中。新的汇总是版本化的,写入后会再次检查查数据的一致性。只有在验证与新版本数据一致后,旧版本的数据才会被删除。为简单起见,在汇总过程中没有加锁,Cassandra负责解决极少的重复写入操作(即最后一个写入操作获胜)。

8043bc8570c5547e0c2e45c5c8d54643f713bf10

图2:实时和压缩的数据模型

如上图所示,CompressedVH中汇总的行也存储元数据信息,如最新版本号,对象大小和块信息(稍后更多)。版本列存储对最新版本的汇总数据进行引用,以便CustomerId的读取始终只返回最新的汇总数据。

汇总起来的数据存储在一个单一的列中,以减少压缩压力。为了最大限度地减少频繁观看模式的会员的汇总频率,最后几天查看历史记录的值将在汇总后保存在LiveVH中,其余部分在汇总期间与CompressedVH中的记录合并。

通过Chunking进行扩展

对于大多数会员来说,将其整个观看记录存储在单行压缩数据中将在读取流程中提升性能。对于一小部分具有大量观看记录的会员,由于第一种体系结构中描述的类似原因,从单行中读取CompressedVH速度缓慢。不常见用例需要在读写延迟上设一个上限,才不会对常见用例造成读写延迟。

为了解决这个问题,如果数据大小大于可配置的阈值,我们将汇总起来的压缩数据分成多个块。这些块存储在不同的Cassandra节点上。即使对于非常大的观看记录数据,对这些块的并行读取和写入也最多只能达到读取和写入延迟上限。

8fa16a04f160e128731778eaedfeea73bb81e8d3

图3:自动缩放通过组块

写流程

如图3所示,根据可配置的块大小,汇总起来的压缩数据被分成多个块。所有块都通过行键:CustomerId $ Version $ ChunkNumber并行写入不同的行。在成功写入分块数据之后,元数据通过行键:CustomerId写入到自己的行。

对于大量观看记录数据的汇总,上述方法将写入延迟限制为两种写入。在这种情况下,元数据行具有一个空数据列,以便能够快速读取元数据。

为了使常见用例(压缩观看记录小于可配置阈值)被快速读取,将元数据与同一行中的观看记录组合以消除元数据查找流程,如图2所示。

读流程

通过关键字CustomerId首次读取元数据行。对于常见用例,块数为1,元数据行也具有最新版本汇总起来的压缩观看记录。对于不常见的用例,有多个压缩的观看记录数据块。使用版本号和块数等元数据信息生成块的不同行密钥,并且并行读取所有块。上述方法将读取延迟限制为两种读取。

缓存层更改

内存缓存层的增强是为了支持对大型条目进行分块。对于具有大量观看记录的会员,无法将整个压缩的观看历史记录放入单个EVCache条目中。与CompressedVH模型类似,每个大的观看历史高速缓存条目被分成多个块,并且元数据与第一块一起被存储。

结果

利用并行,压缩和改进的数据模型,实现了所有目标:

8481c8f592b7f349aa84a1de5c171db681516edf 通过压缩缩小存储空间。

8481c8f592b7f349aa84a1de5c171db681516edf通过分块和并行的读/写操作保证读/写一致性。常见用例的延迟受限于一次读操作和一次写操作,以及不常见用例的延迟受限于两次读操作和两次写操作。

771aaba605c2a106ded13a33498a11086c3a79d4

图4:结果

数据大小减少了约6倍,花费在Cassandra维护上的系统时间减少了约13倍,平均读取延迟减少了约5倍,平均写入延迟减少了约1.5倍。更重要的是,它为团队提供了可扩展的架构和空间,可以适应Netflix观看记录数据的快速增长。


原文发布时间为:2018-03-13

本文作者:文摘菌

本文来自云栖社区合作伙伴“大数据文摘”,了解相关信息可以关注“大数据文摘”微信公众号

相关文章
|
4月前
|
数据可视化
实时榜单排行计算
实时榜单排行计算
120 0
实时榜单排行计算
|
9月前
|
人工智能 数据可视化 JavaScript
基于新浪微博海量用户行为数据、博文数据数据分析:包括综合指数、移动指数、PC指数三个指数
基于新浪微博海量用户行为数据、博文数据数据分析:包括综合指数、移动指数、PC指数三个指数
基于新浪微博海量用户行为数据、博文数据数据分析:包括综合指数、移动指数、PC指数三个指数
|
10月前
|
存储 算法 数据可视化
将330亿参数大模型「塞进」单个消费级GPU,加速15%、性能不减
将330亿参数大模型「塞进」单个消费级GPU,加速15%、性能不减
158 0
|
11月前
|
机器学习/深度学习 存储 缓存
每秒10亿次更新、实现秒级同步延迟,腾讯深度学习推荐系统首次入选OSDI顶会(2)
每秒10亿次更新、实现秒级同步延迟,腾讯深度学习推荐系统首次入选OSDI顶会
123 0
|
11月前
|
机器学习/深度学习 存储 缓存
每秒10亿次更新、实现秒级同步延迟,腾讯深度学习推荐系统首次入选OSDI顶会(1)
每秒10亿次更新、实现秒级同步延迟,腾讯深度学习推荐系统首次入选OSDI顶会
|
12月前
|
SQL 存储 自然语言处理
最近搞了个毫秒级返回百亿数据!我都做了啥! 上
最近搞了个毫秒级返回百亿数据!我都做了啥! 上
|
存储 架构师 文件存储
云端渲染时长1.58亿核小时,阿里云助力国漫巨制《新神榜:杨戬》提升视效
阿里云E-HPC为影视渲染全流程量身定做的方案有幸成为诸多中国数字内容创作佳片后的推手,带来生产关系的改变
云端渲染时长1.58亿核小时,阿里云助力国漫巨制《新神榜:杨戬》提升视效
|
数据采集 分布式计算 关系型数据库
离线计算-国内查询转换率|学习笔记
快速学习离线计算-国内查询转换率
99 0
|
数据采集 大数据 开发者
离线数据计算-国际查询转换率及其他|学习笔记
快速学习离线数据计算-国际查询转换率及其他
66 0
|
SQL 存储 大数据
10亿+/秒!看阿里如何搞定实时数仓高吞吐实时写入与更新
10亿+/秒!看阿里如何搞定实时数仓高吞吐实时写入与更新
3751 2
10亿+/秒!看阿里如何搞定实时数仓高吞吐实时写入与更新