如何以毫秒为单位查询HBase表中的数据?

时间:2016-08-17 05:33:49

标签: redis pagination hbase

我正在编写一个界面来查询来自Hbase表的分页数据,我通过某些条件查询分页数据,但它非常慢。我rowkey这样:12345678:yyyy-mm-dd ,8个随机数和日期的长度。我尝试使用Redis缓存所有rowkeys并在其中进行分页,但是其他条件查询数据很困难。   我还考虑在Hbase中设计二级索引,并与同事讨论,他们认为二级索引很难维护。   那么,谁能给我一些想法?

3 个答案:

答案 0 :(得分:3)

首先,如果您使用大数据进行扩展,AFAIK随机数+ rowkey的日期模式可能会导致热点。

关于分页:

如果您使用的是solr,那么我会提供hbase + cloudera cloudera search。它提供了良好的性能(在我们的案例中证明),每页查询100个,并且通过webservice调用,我们填充了angularjs仪表板。

此外,最重要的是 可以在页面之间来回移动 ,而不会出现任何问题。

下图描述了。

enter image description here

要实现这一点,您需要创建集合(来自hbase数据)并且可以使用solrj api

单独使用带有扫描api的Hbase不适用于快速查询。

除此之外,请看我的答案。这对实施细节更有洞察力......

How to achieve pagination in HBase?

仅Hbase解决方案可以是Hindex(基于协处理器的解决方案)

Link详细解释

Hindex架构:

enter image description here

答案 1 :(得分:1)

在Hbase中,为了获得良好的读取性能,您希望通过少量获取(单行请求)或小扫描(请求超过行范围)来检索数据。 Hbase存储按键排序的数据,因此最重要的想法是提出允许它的行键。 您的密钥似乎只包含随机整数和日期,因此我假设您的查询是关于标记为时间的记录的分页。

第一个想法是,在典型的分页场景中,您一次只能访问1个页面并从第1页导航到第2页到第3页等等。鉴于您希望对2015-08-16日期的所有记录进行分页,您可以使用使用开始键'\ 0:2015-08-16'扫描50行(因为它小于2015-08-16中的任何行)以检索第一页。检索完第一页后,您可以从第一页获得最后一个密钥,例如'12345:2015-08-16'。您可以使用它(或12346:2015-08-16)使用50行的开始键12346:2015-08-16进行另一次扫描以检索第2页,依此类推。因此,使用此方法可以快速查询页面,只需使用预定义的返回行数进行单次扫描。因此,您可以将最后一页的行键用作分页API的参数,或者只将最后一行键放在redis中,以便下一个分页API调用可以在那里找到它。

所有这一切都非常有效,直到某些用户进入并直接点击第100页。或者当他在第2页时尝试点击第5页。在这种情况下,您可以使用nSkippedPages * 50行的类似扫描。这不会像顺序访问那么快,但它不是通常的页面使用模式。您可以使用redis将页面结果的最后一行缓存到pageNumber - >之类的结构中。 rowKey。然后,如果下一个用户点击第100页,它将看到与通常点击页面相同的性能1-点击页面2-点击第3页场景。

然后,为了让第一次点击第99页的用户更快,你可以编写一个单独的守护进程,它检索每隔50行并将结果作为页面索引放入redis。然后每10-15分钟启动一次,并说您的页面索引最多有10-15分钟的陈旧数据。

您还可以设计一个单独的API,为大量N页预加载行密钥(比如大约100页,它可能是异步的,例如不要等待实际的预加载完成)。它只需扫描KeyOnlyFilter和50 * N结果,然后选择每个页面的rowkeys。所以它接受rowkey并用N行的rowkey缓存填充redis。然后当用户走进第一页时,您可以为他获取前100页的行键,这样当他点击页面上显示的某个页面链接时,页面开始行键将可用。使用正确的预加载大小,您可以达到所需的延迟。

可以使用Scan.setMaxResults()或使用PageFilter来实现限制。 “跳过nPages * 50行”,特别是“每50行输出”功能似乎比较棘手,例如对于后者,您可能最终执行完全扫描以检索密钥或编写map-reduce来执行此操作,并且首先不清楚如何在不通过网络发送行的情况下执行此操作,因为请求可以分布在多个区域中。

答案 2 :(得分:0)

如果您正在寻找在HBase中维护的二级索引,则有几个开源选项(Splice Machine,Lilly等)。您可以在几毫秒内完成索引查找。