作者:ketan duvedi,金华李,Dhruv Garg,Philip Fisher-Ogden
介绍
互联网连接设备的增长导致了大量易于访问的时间序列数据。越来越多,公司有兴趣挖掘此数据以获得有用的见解并进行数据通知的决策。最近的技术进步提高了收集,存储和分析时间序列数据的效率,促使增加的胃口来消耗该数据。然而,这种时间序列数据可以压倒最初始的时间序列数据架构。
Netflix是一个数据知情人士,对这些挑战的陌生人毫无陌生,多年来增强了其管理增长的解决方案。在这款2部分博客文章中,我们将分享Netflix如何通过规模的多个增加来演变时间序列数据存储体系结构。
时间序列数据 - 成员查看历史
Netflix成员每天观看超过140万小时的内容。查看标题时每个成员提供多个数据点,并且它们被存储为查看记录。NetFlix分析查看数据,并提供实时准确的书签和这些帖子中所述的个性化建议:
- 我们如何知道您在演出中的位置?
- 帮助您找到展示继续观看Netflix
查看历史数据沿以下3个维度增加:
- 随着时间的推移,每个成员存储更多的查看数据。
- 随着成员计数的增长,查看数据被存储为更多成员。
- 随着成员每月查看时间的增加,每个成员都存储更多的查看数据。
随着Netflix流媒体在前10年中增长到100米+全球成员,观看历史数据的大规模增加。在本博客文章中,我们将专注于我们如何对观看历史数据进行缩放存储的大挑战。
简单的开始
查看历史存储体系结构的第一个云本机版本使用Cassandra原因:
- Cassandra对建模时间序列数据具有良好的支持,其中每行可以具有动态的列。
- 查看历史数据写入读取比率约为9:1。由于Cassandra具有高效的写入,因此这款写繁重的工作量适合Cassandra。
- 考虑到CAP定理,团队最终丧失可用性损失。Cassandra通过可调一致性支持此权衡。
在初始方法中,每个成员的查看历史记录在Cassandra中存储在Cassandra中,其中包含行键:CustomerID。这种水平分区使能有效的缩放与成员的增长,并使常见用例阅读成员的整个观看历史非常简单和高效。然而,随着成员计数增加,更重要的是,每个成员流越来越多的标题,行大小以及总数据尺寸的增加。随着时间的推移,这导致了高存储器和运营成本以及具有大观看历史的成员的表现较慢。
下图说明了初始数据模型的读写流:
写流程
当成员开始播放标题时,一个查看记录被插入为新列。查看记录在会员暂停或停止标题后更新。这款单列写入快速有效。
读流程
全行读取以检索一个成员的所有观看记录:当每个成员的记录数量小时,读取是有效的。由于会员观看了更多的标题,观看记录的数量增加。读取具有大量列的行为Cassandra对读取延迟产生负面影响的额外压力。
时间范围查询读取成员数据的时间片:这导致与上面相同的不一致性能,具体取决于指定时间范围内的查看记录的数量。
全行通过分页读取大型观看历史:这对Cassandra更好,因为它不等待在发送回来之前要准备好的所有数据。这也避免了客户超时。然而,随着查看记录的数量增加,它会增加整个行的总体延迟。
放缓原因
让我们来看看一些Cassandra内部,了解为什么我们的最初简单的设计放慢了速度。随着数据的增长,SSStables的数量相应增加。由于最近的数据仅在内存中,因此在许多情况下,Memtables和SSStable都必须读取以检索查看历史记录。这对读取延迟产生了负面影响。同样,随着数据大小的增加,Compaction采用了更多的iOS和时间。阅读修复和全柱修复变得慢,因为行越来越宽。
缓存层
Cassandra进行了非常好的读写历史数据,但需要改善读取的延迟。为了优化读取延迟,在写入路径期间的工作增加,我们在Cassandra存储前添加了内存分片缓存层(EVCache)。缓存是一个简单的键值存储,其中键是CustomerID和值是查看历史数据的压缩二进制表示。每次写入Cassandra都会产生额外的缓存查找,并且在缓存中,新数据与现有值合并。查看历史记录首先由缓存提供服务。在缓存未命中,从Cassandra读取条目,压缩,然后插入缓存中。
随着缓存层的添加,这种单一的Cassandra表储存方法多年来工作得很好。基于CustomerID的分区在Cassandra Cluster中缩放良好。到2012年,观看历史Cassandra Cluster是Netflix最大的专用Cassandra集群之一。进一步扩展,该团队需要将群集大小加倍。这意味着对Netflix的Cassandra的使用冒险进入未知的领土。与此同时,Netflix业务继续迅速增长,包括增加国际成员基础,即将出于原始内容的不断发展。
重新设计:Live和压缩存储方法
很明显,在未来5年内预期的增长需要不同的方法。该团队分析了数据特征和使用模式,并重新设计了查看历史存储,以两个主要目标:
- 较小的存储足迹。
- 一致的读/写性能是每个成员的查看。
对于每个成员,查看历史数据分为两组:
- LIVE或最近查看历史(LiveVH):少量近期查看记录,频繁更新。数据以未压缩的形式存储,如在上面详述的简单设计中。
- 压缩或存档查看历史记录(CompressiveVH):大量较旧的查看记录,具有罕见更新。数据被压缩以减少存储空间。压缩查看历史记录存储在每行密钥的单个列中。
LiveVH和CompressVH存储在不同的表中,并进行不同的调整以实现更好的性能。由于LiveVH具有频繁更新和少量的查看记录,因此复数频繁运行,GC_GRACE_SECONDS很小,以减少SSSTABLE和数据大小。读取修复和全列家庭修复经常运行以提高数据一致性。由于对压缩的更新是罕见的,因此手动和不经常的全部作品足以减少SSSStables数量。在罕见更新期间检查数据的一致性。这消除了对读取修复的需求以及全柱家庭修复。
写流程
新的查看记录使用相同的方法写入LiveVH,如前所述。
读流
为了获得新设计的好处,可以使用选项更新查看历史证明API来读取最近或完整数据:
- 最近的观看历史:大多数情况下,这导致仅从LiveVH读取,这限制了数据大小导致的更低延迟。
- 完整的观看历史:实现为LiveVH和CompressVH的并行读数。由于数据压缩和具有较少列的压缩,读取的数据较少,从而显着加速读取。
comgressvh更新流程
如果阅读从LiveVH查看历史记录,则记录的数量超过可配置阈值,则通过后台任务卷起最近的查看记录,压缩并存储在CompressVH中。卷起的数据存储在带有行键的新行中:CustomerID。新汇总是版本的,读取后读取以检查一致性。只有验证新版本的一致性后,删除了旧版本的卷起数据。为简单起见,Rollup期间没有锁定,Cassandra负责解决非常罕见的重复写入(即,最后一个作者赢)。
如图2所示,ComuredringVH中的卷起行还存储像最新版本,对象大小和块状信息的元数据信息(稍后更多)。版本列存储引用最新版本的卷起的数据,以便为CustomerID读取始终返回最新的卷起数据。卷起的数据存储在单个列中以减少压力压力。为了最大限度地减少具有频繁观看模式的成员的汇总的频率,只需在汇总后汇总在LiveVH中保存在LiveVH中的最后几天,其余在汇总期间与CompressVH中的记录合并。
通过块自动缩放
对于大多数成员来说,在单行压缩数据中存储其整个观看历史,导致读取流期间的性能良好。对于具有非常大的观看历史的一小部分成员,由于第一架构中所述的类似原因,从单个行开始读取压缩VH开始减慢。对于这种罕见的情况,需要在读取和写入延迟上具有上限,而不会对常用案例的读写延迟产生负面影响。
要解决此问题,如果数据大小大于可配置阈值,我们将卷起的压缩数据拆分为多个块。这些块存储在不同的Cassandra节点上。这些块的并行读取和写入导致读取和写入延迟的上限,即使对于非常大的观看数据。
写流程
如图3所示,卷起压缩数据基于可配置的块大小将压缩数据分成多个块。所有块都与不同行编写的行键编写:CustomerID $ Version $ ChunkNumber。元数据用行密钥写入自己的行:CustomerID成功写入块数据后。这将写入延迟绑定到两个写入非常大的查看数据的汇总。在这种情况下,元数据行具有空数据列,以便快速读取元数据。
为了使常见的情况(压缩查看数据小于可配置阈值),元数据与同一行中的观看数据组合以消除元数据查找开销,如图2所示。
读流
首先使用CustomerID作为密钥读取元数据行。对于常见的情况,块计数为1,元数据行还具有最新版本的卷起压缩查看数据。对于罕见的情况,有多个压缩观看数据块。使用版本和块数等元数据信息,生成块的不同行键,并行读取所有块。这将读取延迟绑定到两个读取。
缓存层更改
内存中缓存层增强以支持大型条目的块。对于具有大型观看历史的成员,无法在单个EVCache条目中符合整个压缩观看历史记录。如此类似于CompressigndVH模型,每个大型观看历史缓存条目被损失到多个块中,并且元数据与第一块一起存储。
结果
通过利用并行性,压缩和改进的数据模型,团队能够满足所有目标:
- 通过压缩较小的存储空间。
- 通过块和并行读/写入一致的读/写性能。延迟绑定到一个读取的常见案例和一个写入绑定到两个读取的延迟和少数读取和稀有案例的两个写入。
该团队的数据尺寸减少了?6倍,减少了在Cassandra维护上花费的系统时间减少了,平均读取延迟降低?5倍,平均写入延迟的降低?1.5倍。更重要的是,它使团队成为可扩展的架构和余量,以适应Netflix查看数据的快速增长。
在此博客文章系列的下一部分中,我们将探讨最新的可扩展性挑战,激励查看历史存储架构的下一次迭代。如果您有兴趣解决类似的问题,请加入我们。
(本文由闻数起舞翻译自undefined的文章《Scaling Time Series Data Storage — Part I》,转载请注明出处,原文链接:https://netflixtechblog.com/scaling-time-series-data-storage-part-i-ec2b6d44ba39)