【发布时间】:2012-01-24 07:45:40
【问题描述】:
我有一个与 HBase 架构设计相关的问题。问题相当简单——我将“通知”存储在 hbase 中,每个通知都有一个状态(“新”、“已见”和“已读”)。以下是我需要提供的 API:
- 获取用户的所有通知
- 获取用户的所有“新”通知
- 获取用户所有“新”通知的计数
- 更新通知状态
- 更新所有用户通知的状态
- 获取数据库中的所有“新”通知
- 通知应该可以按时间倒序扫描并允许分页。
我有一些想法,我想看看其中一个显然是最好的,或者我是否完全错过了一个好的策略。对于这三者来说,我认为每个通知都有一行,并且在 rowkey 中有用户 ID 是要走的路。为了获得分页的时间顺序,我也需要有一个反向时间戳。我想将所有通知保存在一个表中(因此我不必为“获取用户的所有通知”调用合并排序)并且不想为二级索引表编写批处理作业(因为更新到计数和状态应该是实时的)。
最简单的方法是(1)行键是“userId_reverseTimestamp”并在客户端过滤状态。这似乎很幼稚,因为我们将通过网络发送大量不必要的数据。
下一种可能性是 (2) 将状态也编码到行键中,因此要么“userId_reverseTimestamp_status”,然后对扫描进行行键正则表达式过滤。我看到的第一个问题是需要在状态更改时删除一行并将通知数据复制到新行(大概每个通知应该恰好发生两次)。此外,由于状态是行键的最后一部分,因此对于每个用户,我们将扫描许多额外的行。这对性能有很大影响吗?最后,为了更改状态,我需要知道之前的状态是什么(构建行键),否则我需要进行另一次扫描。
我的最后一个想法是 (3) 有两个列族,一个用于静态通知数据,一个作为状态标志,即“s:read”或“s:new”和“s”作为 cf 和 status 作为限定符。每行只有一个,我可以针对该 cf 执行 MultipleColumnPrefixFilter 或 SkipFilter w/ ColumnPrefixFilter。在这里,我也必须在状态更改时删除和创建列,但它应该比复制整行更轻量级。我唯一担心的是 HBase 书中的警告,即 HBase 不能很好地处理“超过 2 或 3 个列族”——也许如果系统需要扩展更多查询功能,multi-cf 策略将无法扩展.
所以 (1) 似乎有太多的网络开销。 (2) 似乎会浪费复制数据的成本,并且 (3) 可能会导致太多家庭出现问题。在 (2) 和 (3) 之间,哪种类型的过滤器应该提供更好的性能?在这两种情况下,扫描都会查看用户的每一行,这可能主要是读取通知 - 这将具有更好的性能。我想我倾向于 (3) - 还有其他我错过的选项(或调整)吗?
【问题讨论】:
-
通知状态是否为“新”和“已读”,只有一个可能的从新到已读的转换?这些通知的数量是多少?