Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/hadoop/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 设计HBase架构以最佳支持特定查询_Java_Hadoop_Nosql_Hbase - Fatal编程技术网

Java 设计HBase架构以最佳支持特定查询

Java 设计HBase架构以最佳支持特定查询,java,hadoop,nosql,hbase,Java,Hadoop,Nosql,Hbase,我有一个与HBase模式设计相关的问题。问题相当简单——我在hbase中存储“通知”,每个通知都有一个状态(“新建”、“查看”和“读取”)。以下是我需要提供的API: 获取用户的所有通知 获取用户的所有“新”通知 获取用户所有“新”通知的计数 更新通知的状态 更新用户所有通知的状态 获取数据库中的所有“新”通知 通知应可按逆时间顺序扫描,并允许分页 我有一些想法,我想看看其中是否有一个显然是最好的,或者我是否完全错过了一个好的策略。这三种方法都是通用的,我认为每个通知有一行,并且在rowke

我有一个与HBase模式设计相关的问题。问题相当简单——我在hbase中存储“通知”,每个通知都有一个状态(“新建”、“查看”和“读取”)。以下是我需要提供的API:

  • 获取用户的所有通知
  • 获取用户的所有“新”通知
  • 获取用户所有“新”通知的计数
  • 更新通知的状态
  • 更新用户所有通知的状态
  • 获取数据库中的所有“新”通知
  • 通知应可按逆时间顺序扫描,并允许分页
我有一些想法,我想看看其中是否有一个显然是最好的,或者我是否完全错过了一个好的策略。这三种方法都是通用的,我认为每个通知有一行,并且在rowkey中有用户id是一种方法。要获得分页的时间顺序,我还需要在其中有一个反向时间戳。我希望将所有通知保存在一个表中(因此我不必为“get all NotificationsN for a user”调用合并排序),也不希望为二级索引表编写批处理作业(因为计数和状态的更新应该是实时的)

最简单的方法是(1)行键是“userId\u reverseTimestamp”,并在客户端对状态进行过滤。这似乎很幼稚,因为我们将通过网络发送大量不必要的数据

下一种可能性是(2)也将状态编码到rowkey中,因此要么“userId\u reverseTimestamp\u status”,然后对扫描执行rowkey正则表达式过滤。我看到的第一个问题是,当状态发生变化时,需要删除一行并将通知数据复制到新行(据推测,每个通知应该恰好发生两次)。另外,由于状态是rowkey的最后一部分,对于每个用户,我们将扫描大量额外的行。这是一个大的性能击中?最后,为了更改状态,我需要知道以前的状态是什么(构建行键),否则我需要进行另一次扫描

我的最后一个想法是(3)有两个列族,一个用于静态notif数据,另一个作为状态的标志,即“s:read”或“s:new”,其中“s”作为cf,status作为限定符。每行正好有一个,我可以对该cf执行多列PrefixFilter或SkipFilter w/ColumnPrixFilter。在这里,我也必须在状态更改时删除和创建列,但它应该比复制整行轻得多。我唯一担心的是HBase手册中的警告,即HBase不能很好地处理“超过2列或3列的系列”-也许如果系统需要扩展更多的查询功能,多cf策略将无法扩展


所以(1)看起来会有太多的网络开销。(2) 似乎这会浪费复制数据的成本,(3)可能会导致太多家庭出现问题。在(2)和(3)之间,哪种类型的过滤器性能更好?在这两种情况下,扫描将为用户查看每一行,这可能主要是读取通知,这将具有更好的性能。我想我倾向于(3)-还有其他选择(或调整)我错过了吗?

你已经对此进行了很多思考,我认为这三个都是合理的

由于大多数查询都是“按用户”进行的,所以您希望主键是与时间戳连接在一起的用户名。这将有助于通过扫描轻松分页,并可以非常快速地获取用户信息

我认为你的问题的关键是这个不断变化的状态部分。一般来说,类似于“read”->“delete”->“rewrite”的操作会引入各种并发问题。如果您的任务在两个任务之间失败,会发生什么情况?您的数据是否处于无效状态?你会放弃一张唱片吗

我建议您改为将表视为“仅附加”。基本上,按照你对#3的建议去做,但是不要去掉旗帜,而是把它放在那里。如果某个内容已经被读取,那么它可以有三个“s:seed”、“s:read”(如果是新的,我们可以假设它是空的)。你也可以想入非非,在三个事件中的每一个都加上一个时间戳,以显示该事件何时得到满足。这样做不会对性能造成太大的影响,而且也不必担心并发性,因为所有操作都是只写操作和原子操作

我希望这是有帮助的。我不确定我是否回答了所有问题,因为你的问题太广泛了。请继续补充问题,我很乐意详细说明或讨论其他问题。

我的解决方案是:

不要在hbase中为每个通知保存通知状态(已看到,新)。对于通知,请使用简单模式。键:userid\u时间戳-列:通知\u消息

一旦客户端请求API“获取所有新通知”,保存时间戳(所有新通知已推送)。Key:userid-colimn:All_new_notification_push_time

每个带有时间戳的通知都低于“所有推送的新通知”,假设为“已看到”,如果更大,则假设为“新”

要获取所有新通知,请执行以下操作: 首先,通过userid获取所有\u新\u通知\u推送\u时间的值(时间戳) 然后按键对通知消息列执行范围扫描:从当前时间戳到所有新通知推送时间

这将大大限制受影响的列,其中大多数应该在memstore中


计算客户端上的新通知。

Gppd指出了如何使其仅写。不必黑客原子更新使它变得不那么复杂-我的过滤器将只是“只要没有未读状态”。有人建议的另一个选项是每行有多个列,其中一行对用户来说都是notifs。据推测,列的排序类似于行。我的问题是,这给了我们什么吗?他们还建议只在notif上做一个ValueFilter(这样就可以在它的数据中保留状态)