我目前正在开发一种将用户当前位置历史存储到HBase表中的解决方案。(假设有数亿用户)。每个用户的位置测试都存储在一个HBase表中。然后,这些位置跟踪被用作很少的脱机数据分析作业的一部分。
以下是两种主要的数据访问模式:
鉴于上述要求,我提出了以下行键设计:
<uid>_<timestamp>其中'uid‘表示用户id,而’时间戳‘表示检测和保存位置的时间。
使用这个行键设计,实现访问模式#1是直接的-扫描请求可以有一个启动键和结束键,并将给定的时间戳附加到特定的uid中。
然而,棘手的部分是访问模式#2,我正在寻求HBase专家的帮助。因为,我需要扫描所有用户说在过去6个月,我将结束不使用任何键扫描操作。这会影响扫描整个HBase表。我觉得效率很低。此外,我的数据大小有望在2K/秒的情况下更快地增长。
我看了一下OpenTSDB,这是许多人在公开论坛上指出的。但我无法将该解决方案与我的数据访问模式联系起来。
我正在寻找优化此模式的帮助,这将避免对整个表进行扫描。
发布于 2013-12-25 03:38:07
与将每个位置点存储在一行中不同,您可以使用一年的TTL将每个位置存储在它自己的列中。这类似于OpenTSDB是如何实现度量的,在特定的时间窗口中,每个度量的读取都存储在一个单独的列中。
此架构将允许您扫描所有用户和扫描作业内部,手动筛选出您不关心的日期。这仍然是一个完整的表扫描,但只对您的用户集,而不是您的所有位置集。
此模式还允许用户只进行一次get或小扫描,以便用户访问其整个位置历史记录。
此模式的缺点在于每个用户的行大小。如果每个用户都有几百个或上千个数据点,那么您应该没事。但是,如果每个用户都有数百万个位置,您的行大小可能会增长到与您的区域相同的大小。由于HBase从不将行划分为多个区域,因此您最终会得到由单个行组成的区域,这不是最优的。
要解决这个问题,您需要像OpenTSDB那样为每个用户实现自己的签入数据存储。假设每个桶都是uid+weekOfTheYear+year。桶粒度在很大程度上取决于用户添加位置数据的频率。这将为每个用户创建多个行,因此需要对给定用户的每个桶进行扫描。若要访问特定日期范围的数据,只需使用时间戳筛选内置的扫描程序即可。
发布于 2013-12-16 18:35:37
您可以做的一件简单的事情就是在键中增加一些时间--例如,添加一个月前缀--在这种情况下,常规查询可能需要查看多个扫描(假设在常用情况下,您只需要最新的记录,而不是大多数情况下),但运行时间越长将被限制在几个月内。
顺便说一句,如果在常规使用中您需要最新的记录,您可能希望存储从最新到最老的日期(maxlong时间戳),这样时间范围上的查询就会更快。
发布于 2013-12-23 10:32:44
就个人而言,我将避免在您的行键中使用基于时间的前缀。
让我向你指出另一个方向,你能负担得起重复的数据吗?
如果答案是肯定的,只需创建另一个表,其中包含作业所需的最小数据,并将TTL设置为6个月(如果需要,则另一个具有3个月TTL的表),然后立即写入所有表(您可以根据需要对该表进行缓冲区写入)。另外,你的桌子上有几个家庭,你可以把那些短暂的家庭加到同一张桌子上,但我更喜欢有不同的家庭(个人喜好)。
如果答案是否定的,您仍然可以进行基于时间戳的范围扫描,以避免读取尽可能多的数据。如果(正如你说的)该表将有一个1年的TTL,你可以负担得起它,这不像做了一个完整的扫描30年的数据,只是检索几天。
顺便说一句,我建议您至少包含一个基于数字uuid的2-3字节前缀(模块化、crc32、md5.)为了在区域间获得均匀分布,并更好地处理不活跃(或非常活跃)用户。你不可能预测你的用户会有多活跃。
https://stackoverflow.com/questions/20611452
复制相似问题