我正在编写一个从hbase表中查询分页数据的接口,我按某些条件查询分页数据,但速度非常慢 rowkey 这样地: 12345678:yyyy-mm-dd ,长度为8个随机数和日期。我尝试使用redis缓存所有 rowkeys 并在其中进行分页,但按其他条件查询数据比较困难。我还考虑在hbase中设计二级索引,并与同事讨论,他们认为二级索引很难维护。那么,谁能给我一些建议?
rowkey
12345678:yyyy-mm-dd
rowkeys
bz4sfanl1#
首先,如果用大数据进行缩放,行键的随机数+日期模式可能会导致热点。
我愿意提供 solr + hbase 如果您正在使用 cloudera 那么它 cloudera search . 它提供了良好的性能(在我们的例子中得到了证明),同时查询每页100个,并且使用我们填充的webservice调用 angularjs Jmeter 板。另外,最重要的是你可以在页面之间来回移动,而不会出现任何问题。。下图描述了这一点。要实现这一点,您需要创建集合(从hbase数据)并可以使用solrjapi
solr
hbase
cloudera
cloudera search
angularjs
除此之外,请看我的答案。在实现细节方面更具洞察力。。。如何在hbase中实现分页?
链接更详细地解释
a64a0gku2#
如果您正在寻找在hbase中维护的二级索引,那么有几个开源选项(splice machine、lilly等)。您可以在几毫秒内完成索引查找。
bn31dyow3#
在hbase中,为了获得良好的读取性能,您需要通过少量get(对单行的请求)或少量扫描(对行范围的请求)来检索数据。hbase存储按键排序的数据,所以最重要的想法是使用这样的行键。您的键似乎只包含随机整数和日期,所以我假设您的查询是关于对标记有时间的记录进行分页的。第一个想法是,在典型的分页场景中,您一次只访问一页,并从第1页导航到第2页,再导航到第3页等。如果您想对日期2015-08-16的所有记录进行分页,您可以使用50行的扫描,并使用开始键“\0:2015-08-16”(因为它比2015-08-16中的任何一行都小)来检索第一页。检索完第一页后,您就有了第一页的最后一个键,比如“12345:2015-08-16”。您可以使用它(或12346:2015-08-16)进行另一次扫描,开始键12346:2015-08-16共50行,以检索第2页,依此类推。因此,使用这种方法,您可以通过预定义的返回行数,以单次扫描的方式快速查询页面。所以您可以使用lastpagerow键作为分页api的参数,或者将lastpagerow键放在redis中,这样下一个分页api调用就会在那里找到它。所有这些工作都非常好,直到一些用户进来直接点击到第100页。或者当他在第二页的时候试着点击第五页。在这种情况下,可以对nskippedpages50行使用类似的扫描。这不会像顺序访问那么快,但它不是一种常见的页面使用模式。然后可以使用redis将页面结果的最后一行缓存在pagenumber->rowkey这样的结构中。然后,如果下一个用户来点击第100页,它将看到与通常点击第1页-点击第2页-点击第3页场景相同的性能。然后,为了让第一次单击第99页的用户能够更快地完成任务,您可以编写一个单独的守护程序,它每50行检索一次,并将结果作为页面索引放入redis。然后每10-15分钟启动一次,并说页面索引最多有10-15分钟的过时数据。您还可以设计一个单独的api,为大量n个页面预加载行键(比如说大约100个页面,它可以是异步的,例如不要等待实际的预加载完成)。它只需扫描keyonlyfilter和50n结果,然后为每个页面选择行键。所以它接受rowkey,并用rowkey缓存填充redis n个页面。然后当用户进入第一个页面时,您将为他获取前100个页面的行键,这样当他单击页面上的某个页面链接时,页面开始行键将可用。有了合适的预加载批量大小,您就可以接近所需的延迟。可以使用scan.setmaxresults()或使用pagefilter实现限制。“跳过npages*50行“和特别是“输出每50行”的功能似乎是棘手的,例如,对于后者,您可能会结束执行完整的扫描检索键或写Map减少这样做,首先它是不清楚如何做,而不通过网络发送行,因为请求可以分布在几个地区。
3条答案
按热度按时间bz4sfanl1#
首先,如果用大数据进行缩放,行键的随机数+日期模式可能会导致热点。
关于分页:
我愿意提供
solr
+hbase
如果您正在使用cloudera
那么它cloudera search
. 它提供了良好的性能(在我们的例子中得到了证明),同时查询每页100个,并且使用我们填充的webservice调用angularjs
Jmeter 板。另外,最重要的是你可以在页面之间来回移动,而不会出现任何问题。。
下图描述了这一点。
要实现这一点,您需要创建集合(从hbase数据)并可以使用solrjapi
hbase单独使用scan-api不适用于快速查询。
除此之外,请看我的答案。在实现细节方面更具洞察力。。。
如何在hbase中实现分页?
只有hbase的解决方案可以是hindex(基于协处理器的解决方案)
链接更详细地解释
hindex体系结构:
a64a0gku2#
如果您正在寻找在hbase中维护的二级索引,那么有几个开源选项(splice machine、lilly等)。您可以在几毫秒内完成索引查找。
bn31dyow3#
在hbase中,为了获得良好的读取性能,您需要通过少量get(对单行的请求)或少量扫描(对行范围的请求)来检索数据。hbase存储按键排序的数据,所以最重要的想法是使用这样的行键。您的键似乎只包含随机整数和日期,所以我假设您的查询是关于对标记有时间的记录进行分页的。
第一个想法是,在典型的分页场景中,您一次只访问一页,并从第1页导航到第2页,再导航到第3页等。如果您想对日期2015-08-16的所有记录进行分页,您可以使用50行的扫描,并使用开始键“\0:2015-08-16”(因为它比2015-08-16中的任何一行都小)来检索第一页。检索完第一页后,您就有了第一页的最后一个键,比如“12345:2015-08-16”。您可以使用它(或12346:2015-08-16)进行另一次扫描,开始键12346:2015-08-16共50行,以检索第2页,依此类推。因此,使用这种方法,您可以通过预定义的返回行数,以单次扫描的方式快速查询页面。所以您可以使用lastpagerow键作为分页api的参数,或者将lastpagerow键放在redis中,这样下一个分页api调用就会在那里找到它。
所有这些工作都非常好,直到一些用户进来直接点击到第100页。或者当他在第二页的时候试着点击第五页。在这种情况下,可以对nskippedpages50行使用类似的扫描。这不会像顺序访问那么快,但它不是一种常见的页面使用模式。然后可以使用redis将页面结果的最后一行缓存在pagenumber->rowkey这样的结构中。然后,如果下一个用户来点击第100页,它将看到与通常点击第1页-点击第2页-点击第3页场景相同的性能。
然后,为了让第一次单击第99页的用户能够更快地完成任务,您可以编写一个单独的守护程序,它每50行检索一次,并将结果作为页面索引放入redis。然后每10-15分钟启动一次,并说页面索引最多有10-15分钟的过时数据。
您还可以设计一个单独的api,为大量n个页面预加载行键(比如说大约100个页面,它可以是异步的,例如不要等待实际的预加载完成)。它只需扫描keyonlyfilter和50n结果,然后为每个页面选择行键。所以它接受rowkey,并用rowkey缓存填充redis n个页面。然后当用户进入第一个页面时,您将为他获取前100个页面的行键,这样当他单击页面上的某个页面链接时,页面开始行键将可用。有了合适的预加载批量大小,您就可以接近所需的延迟。
可以使用scan.setmaxresults()或使用pagefilter实现限制。“跳过npages*50行“和特别是“输出每50行”的功能似乎是棘手的,例如,对于后者,您可能会结束执行完整的扫描检索键或写Map减少这样做,首先它是不清楚如何做,而不通过网络发送行,因为请求可以分布在几个地区。