用于存储视频帧的 HBase 架构设计:行与列,行作为列

Posted

技术标签:

【中文标题】用于存储视频帧的 HBase 架构设计:行与列,行作为列【英文标题】:HBase schema design to store video frames: rows vs columns, rows as columns 【发布时间】:2017-06-17 15:57:38 【问题描述】:

一位朋友问我如何在 HBase 中逐帧存储原始视频。典型的访问模式是在一段时间内检索帧。每帧大约是。 7MB,素材以每秒约 30 帧的速度拍摄。例如,一个 20 分钟的视频大约需要 250GB 的存储空间。

我看到了 HBase: the definitive guide 的作者 Lars George 的精彩视频,标题为 HBase Schema Design: things you need to know,他在其中谈到了存储视频“块”(他谈到视频的 sn-p 开始于 1:07:12 和结束于 1:08:52),所以看起来 HBase 可能适合这个用例。

我创建了几个行键选项:

场景0:rowkey=视频ID+时间戳;单列中的框架(又高又瘦的桌子),例如

key                     col
video1|1497567476.123   image=[image BLOB]
video1|1497567476.156   image=[image BLOB]
...
video1|1497567536.014   image=[image BLOB]

优点:

简单

缺点:

由于键是连续的,我们阅读时的热点

场景一:rowkey = hash(video ID + round(timestamp, 1 minute)) + timestamp;单列中的框架,例如

key                                             col
18ba6892ce0933ece7282b1f2971b3fd|1497567536.014 image=[image BLOB]
...
2ea8ce843615408fb19f8d6e44df32c7|1497567476.123 image=[image BLOB]
2ea8ce843615408fb19f8d6e44df32c7|1497567476.156 image=[image BLOB]

rowkey 有一个前缀,可确保一分钟的块分布在整个集群中,并且在一分钟的块中,帧按连续的时间顺序排列。

优点:

跨区域分布的块,并且在每个块内,读取将是顺序的。这是一种折衷方案,允许顺序读取跨 HBase 区域分布数据。

缺点:

有点不灵活;不确定最佳的块时间窗口应该是多少,一旦设置,就很难改变

场景二:rowkey = hash(video ID + round(timestamp, 1 minute));列中的帧从“基本”时间偏移(列类似于 OpenTSDB):

key                              col:base_time + (0 * x millis) col:base_time + (1 * x millis)  col:base_time + (2 * x millis)
18ba6892ce0933ece7282b1f2971b3fd image=[image BLOB]             ...                             ...
2ea8ce843615408fb19f8d6e44df32c7 image=[image BLOB]             image=[image BLOB]              [image BLOB]

优点:

模式已被 OpenTSDB 证明适用于时间序列指标(参见 this presentation 中的幻灯片 13)

缺点:

非常大的行,这对于 HBase 通常不是一个好主意

对于视频帧的最佳 rowkey 设计,是否有人有任何建议或见解?

注意:我知道几个类似的例子,它们不是使用 HBase 来存储视频片段,而是使用具有单独索引的序列文件或 .har 文件来捕获元数据以允许随机访问。现在,我想专注于 HBase:特别是行键设计。

【问题讨论】:

【参考方案1】:

视频每秒有 200MB 的数据(每帧 7MB * 30 fps)。

当单元格较小时,数据局部性是一件好事,从单台机器读取所有内容然后等待所有机器返回结果会更快。加载 5 秒的视频 (1GB) 对于单机磁盘 IO 来说已经是一个巨大的负载,因此数据本地化无济于事。

我相信加盐/加前缀是这里最好的解决方案

key = hash(video_id, timestamp) + video_id + timestamp

您将在整个集群中获得均匀的数据分布并分散负载。您可以将帧存储在单独的列中的单行中,也可以将 frame_id 添加到键中,没关系。

为了获得更好的性能,您还需要设置正确的 CF 大小设置以适合您的数据。

【讨论】:

【参考方案2】:

我喜欢你的方法,但我建议使用 (videoID % number_of_regions) + videoID + timestamp。这样您就不会被限制在 1 分钟的限制内,但读取是连续的,并且整个视频都存储在同一区域中。

【讨论】:

以上是关于用于存储视频帧的 HBase 架构设计:行与列,行作为列的主要内容,如果未能解决你的问题,请参考以下文章

深入学习Hbase架构原理

HBase与列存储

C# DataTable 增加行与列

Hbase

Hbase 性能行键与列限定符

汇编输入行与列实现对二维数组的查询