java - 设计 HBase 模式以最好地支持特定查询

标签 java hadoop nosql hbase

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

  • 获取用户的所有通知
  • 获取用户的所有"new"通知
  • 获取用户所有"new"通知的计数
  • 更新通知状态
  • 更新用户所有通知的状态
  • 获取数据库中的所有"new"通知
  • 通知应该可以按时间倒序浏览并允许分页。

我有几个想法,我想看看其中一个是否显然是最好的,或者我是否完全错过了一个好的策略。这三者的共同点是,我认为每个通知只有一行,并且在行键中包含用户 ID 是可行的方法。为了获得分页的时间顺序,我也需要在那里有一个反向时间戳。我想将所有通知保存在一个表中(这样我就不必为“获取用户的所有通知”调用进行合并排序)并且不想为二级索引表编写批处理作业(因为更新到计数和状态应该是实时的)。

最简单的方法是 (1) 行键是“userId_reverseTimestamp”并在客户端过滤状态。这看起来很天真,因为我们将通过网络发送大量不必要的数据。

下一个可能性是 (2) 也将状态编码到 rowkey 中,所以要么是“userId_reverseTimestamp_status”,然后对扫描进行 rowkey regex 过滤。我看到的第一个问题是需要在状态更改时删除一行并将通知数据复制到新行(大概每个通知应该恰好发生两次)。此外,由于状态是行键的最后一部分,对于每个用户,我们将扫描大量额外的行。这是一个很大的性能打击吗?最后,为了更改状态,我需要知道之前的状态是什么(以构建行键),否则我将需要进行另一次扫描。

我的最后一个想法是 (3) 有两个列族,一个用于静态通知数据,一个作为状态标志,即“s:read”或“s:new”和“s”作为 cf 和状态作为预选赛。每行只有一个,我可以针对该 cf 执行 MultipleColumnPrefixFilter 或 SkipFilter w/ColumnPrefixFilter。在这里,我也必须删除和创建有关状态更改的列,但它应该比复制整行轻得多。我唯一担心的是 HBase 书中的警告,即 HBase 不能很好地处理“超过 2 或 3 个列族”——也许如果系统需要扩展更多查询功能,multi-cf 策略将无法扩展.

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

最佳答案

你考虑的很周到,我觉得三者都有道理!

您希望主键是用户名和时间戳,因为您的大部分查询都是“按用户”进行的。这将有助于通过扫描轻松分页,并且可以非常快速地获取用户信息。

我认为你的问题的症结在于这个不断变化的状态部分。一般来说,诸如“读取”->“删除”->“重写”之类的操作会引入各种并发问题。如果你的任务失败了怎么办?您是否有处于无效状态的数据?你会放弃记录吗?

我建议您改为将表格视为“仅追加”。基本上,按照您对 #3 的建议进行操作,但不要移除标志,而是将其保留在那里。如果有东西被读过,它可以有三个“s:seen”、“s:read”(如果它是新的,我们可以假设它是空的)。您也可以花哨的时间在这三个事件中的每一个中放置一个时间戳,以显示该事件何时得到满足。执行此操作不会对性能造成太大影响,而且您不必担心并发性,因为所有操作都是只写和原子操作。

希望对您有所帮助。我不确定我是否回答了所有问题,因为你的问题太宽泛了。请跟进其他问题,我很乐意详细说明或讨论其他内容。

关于java - 设计 HBase 模式以最好地支持特定查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8983503/

相关文章:

java - 关于在 hdfs 中传输文件

design-patterns - 使用 NoSQL 时是否有设计模式的良好资源?

java - 在tomcat上部署的servlet中写入文件的问题

hadoop - 根据输入数字生成不同数量的列

hadoop - 无法将数据加载到 hive 表中

nosql - 在Elasticsearch中,多个顶级文档可以共享一个嵌套文档吗?

firebase - Firestore (NoSQL) 是社交媒体应用程序的不错选择吗?

java - 我们何时以及为什么需要 ApplicationRunner 和 Runner 接口(interface)?

java - 运行脚本以使用 HSQLDB 创建表

java - 编译错误序列: Static compilation error coming after resolving access modifier error?