一位朋友问我如何在hbase中逐帧存储原始视频。典型的访问模式是检索一个时间段的帧。每帧约为7mb,每秒钟可拍摄30帧。例如,一个20分钟的视频需要大约250gb的存储空间。
我看到了一个很棒的视频,作者是《hbase:the definal guide》,名为hbase schema design:things you needed to know,其中他谈到了存储视频“chunks”(他谈到的视频片段开始于1:07:12,结束于1:08:52),所以hbase似乎有可能适合这个用例。
我创建了两个行键选项:
场景0:rowkey=video id+时间戳;单列框架(高而瘦的table),例如。
key col
video1|1497567476.123 image=[image BLOB]
video1|1497567476.156 image=[image BLOB]
...
video1|1497567536.014 image=[image BLOB]
优势:
简单
缺点:
因为键是连续的,所以我们读的时候是热点
场景1:rowkey=hash(视频id+round(timestamp,1分钟))+时间戳;单列框架,例如。
key col
18ba6892ce0933ece7282b1f2971b3fd|1497567536.014 image=[image BLOB]
...
2ea8ce843615408fb19f8d6e44df32c7|1497567476.123 image=[image BLOB]
2ea8ce843615408fb19f8d6e44df32c7|1497567476.156 image=[image BLOB]
rowkey有一个前缀,确保一分钟的块分布在集群中,并且在一分钟的块中,帧以连续的时间顺序排列。
优势:
块分布在不同的区域,在每个块中,读取是顺序的。这是一种折衷方案,允许按顺序读取数据并跨hbase区域分发数据。
缺点:
有点呆板;不确定最佳块时间窗口应该是什么,一旦设置好,就很难改变
场景2:rowkey=hash(视频id+round(时间戳,1分钟));列中的帧与“基本”时间偏移(列类似于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已经证明,该模式对于timeseries度量非常有效(请参阅本演示中的幻灯片13)
缺点:
非常大的行,这对于hbase通常不是一个好主意
有人对视频帧的最佳行键设计有什么建议或见解吗?
注意:我知道几个类似的例子,它们不是使用hbase来存储视频片段,而是使用序列文件或带有单独索引的.har文件来捕获元数据以允许随机访问。现在,我想重点讨论hbase:特别是rowkey设计。
2条答案
按热度按时间xxls0lw81#
我喜欢你的方法,但我建议使用(videoid%number\u of \u regions)+videoid+时间戳。这样你就不受1分钟的限制,但读取是连续的,整个视频存储在同一个区域。
m0rkklqb2#
视频每秒有200mb的数据(每帧7mb*30fps)。
当单元很小时,数据局部性是一件好事,它可以更快地从一台机器读取所有内容,然后等待所有机器返回结果。加载5秒的视频(1gb)对于单机磁盘io来说已经是一个巨大的负载,因此数据局部性并没有帮助。
我相信在钥匙上加盐/前缀是最好的解决办法
您将在集群中获得均匀的数据分布并分散负载。可以将帧存储在单独的列中的一行中,也可以将帧id添加到键中,这无关紧要。
为了获得更好的性能,您还需要设置正确的cf大小设置以适合您的数据。