0

我正在为我的 Bigtable 寻找一个最佳方案,以通过指定年份(或完整日期)、国家和(或)城市来满足查询数据的要求。我曾考虑将我的行键命名为2019.us.NYC,然后通过前缀查询它,但这是一个坏主意,因为它只会将我的所有数据存储在一个节点上,直到 2020 年到来,而不是共享给其他节点。有任何想法吗?也许有人已经有了这样的案例?这里的瓶颈是每秒将有大约 50 000 000 行新行。

编辑:也许使用 BigQuery 更好?

4

1 回答 1

2

以下是一个可能的解决方案,根据您的要求:

  • 每秒 50'000'000 次写入
  • 数据访问的低延迟
  • 查询总是包含yearand country,可选month的 , dayandcity

year+country

由于year并且country始终存在于您的查询中,因此它们必须位于行键的开头,例如:

  • 2018#de
  • 2019#de
  • 2019#us

(我曾经在这里定界,但如果和总是分别定义在 4 和 2 个字符上#可能没用。您可以将其删除以节省一个字节!)。yearcountry

month+ day+city

因为month,daycity是可选的,所以它们也可以出现在行键上,而是出现在末尾:

  • 2018#de#0610#frankfurt
  • 2019#de#0115#berlin
  • 2019#us#0813#nyc

我建议您根据需要重新排序元素(如果使用year,country和的查询city是最常见的,那么顺序应该是year#country#city)。只有您可以知道最频繁的查询。始终有必要在设计行键时考虑到您的查询

避免热点

但是,正如您在问题中所建议的那样,这种行键设计可能导致 Bigtable 节点热点(所有写入单个节点,因为行键是连续的)。为了解决这个问题并确保节点之间行键的完美分布,我建议您使用分桶。

对于每次写入,您可以生成一个随机数(介于 0 和 8 之间,例如,如果您需要 8 个存储桶),并将该存储桶编号添加到您的行键中。例如 :

  • 3#2018#de#0610#frankfurt
  • 2#2019#de#0115#berlin
  • 7#2019#us#0813#nyc

然后,您将确保在编写时您的密钥将正确分布在您的 Bigtable 节点上。

您可以查看此链接,了解如何在 HBase(Bigtable 等效项)上执行此操作:https ://hbase.apache.org/book.html#schema.casestudies.log_timeseries.tslead 。

查询数据

但是由于这种分桶(或加盐),您需要更改查询表的方式。如果您想要美国 2019 年的所有数据,则需要执行 8 次扫描(每个存储桶一次):

  • 开始键:0#2019#us#,结束键:0#2019#us~
  • 开始键:1#2019#us#,结束键:1#2019#us~
  • 开始键:2#2019#us#,结束键:2#2019#us~
  • 开始键:3#2019#us#,结束键:3#2019#us~
  • 开始键:4#2019#us#,结束键:4#2019#us~
  • 开始键:5#2019#us#,结束键:5#2019#us~
  • 开始键:6#2019#us#,结束键:6#2019#us~
  • 开始键:7#2019#us#,结束键:7#2019#us~

(我~在 end 键的末尾使用,因为~在 ASCII 表中是在 . 之后的所有可能字符#。例如,对于第一次扫描,这可以确保0#2019#us#检索到所有开头的行键)

这些扫描可以并行执行以获得最佳性能。

扫描是在 Bigtable 中查询数据的最高效方式。您还可以使用一些过滤器(例如FuzzyRowFilter使用特定正则表达式查询行键),但扫描肯定会给您带来更好的延迟。您还可以执行扫描并在扫描后使用过滤器(例如,要检索2019inus中的所有数据nyc,需要过滤器以仅获取带有 的行city = nyc)。

结论

因此,基于这些元素,我将设计我的密钥,例如:

<bucket_number>#<year>#<country>#<month><day>#<city>

使用扫描查询我的表。#如果所有字段都具有固定长度,则分隔符(此处)是无用的。

如果您有足够数量的<country>值将密钥分配到不同的节点,您也可以有一些没有分桶的变体:

<year>#<country>#<month><day>#<city>

或者 :

<country>#<year>#<month><day>#<city>

总之,在设计 Bigtable 行键时总是需要权衡取舍。通过使用分桶,您始终可以避免热点,但查询数据的方式更加复杂。但是,根据您的要求(许多写),这就是我要做的。

您还可以根据 Bigtable 集群中的节点数来更改存储桶的数量。如果您有超过 8 个节点,我建议您创建更多存储桶。理想情况下,1 个桶 = 1 个节点,但一个节点可以轻松包含多个桶。

我建议尽管与其他人一起测试这个关键设计,并在真实条件下(PoC)对它们进行基准测试。您可以使用Bigtable Key Visualizer检查您的密钥在集群中的分布情况。

于 2019-08-13T18:45:44.967 回答