Cassandra用于无模式数据库,每天有数百万个订单表和数百万个查询

时间:2012-08-07 13:26:31

标签: cassandra

我正在构建一个具有以下特征的数据库:

  1. 每行具有可变列数的无架构数据库。
  2. 数千万条记录和数十列。
  3. 每天数百万次查询。
  4. 每天写入数千篇文章。
  5. 查询将过滤多个列(不仅是键)。
  6. 我正在考虑按比例建造的Cassandra。

    我的问题是:

    1. 在这种情况下我需要水平缩放吗?
    2. Cassandra是否支持使用多个键指向同一列族?

    3. 编辑

      我想确保我的观点正确无误。所以,下面的例子说明了你从答案中得到的结论:

      因此,如果我们有以下列系列(它包含一些商店产品及其详细信息)

      products // column-family name
      {
      x = {   "id":"x", // this is unique id for the row. 
          "name":"Laptop",
          "screen":"15 inch",
          "OS":"Windows"}
      y = {   "id":"y", // this is unique id for the row. 
          "name":"Laptop",
          "screen":"17 inch"}
      z = {   "id":"z", // this is unique id for the row. 
          "name":"Printer",
          "page per minute":"20 pages"}
      }
      

      并且,我们想要添加“name”搜索参数,我们将使用不同的行键创建另一个CF副本,如下所示:

      products
      {
      "x:name:Laptop"  = {    "id":"x", 
                  "name":"Laptop",
                  "screen":"15 inch",
                  "OS":"Windows"}
      "y:name:Laptop"  = {    "id":"y", 
                  "name":"Laptop",
                  "screen":"17 inch"}
      "z:name:Printer" = {    "id":"z", 
                  "name":"Printer",
                  "ppm":"20 pages"}
      }
      

      同样,为了添加“屏幕”搜索参数:

      products
      {
      "x:screen:15 inch" = {  "id":"x" 
                  "name":"Laptop",
                  "screen":"15 inch",
                  "OS":"Windows"}
      "y:screen:17 inch" = {  "id":"y", 
                  "name":"Laptop",
                  "screen":"17 inch"}
      }
      

      但是,如果我们想根据10个搜索参数或它们的任意组合(如我的应用程序中的情况)进行查询,那么我们将不得不创建1023个列系列的副本[(2) 10)-1]。并且由于大多数行将具有许多搜索参数,这意味着我们需要大约1000倍的额外存储来建模数据(以这种方式),这不是很少,特别是如果我们在原始CF中有10,000,000行。

      这是您建议的数据模型吗?

      <小时/> 另一点:我无法确切地了解为什么创建二级索引会放弃或剥夺无模式模型。

1 个答案:

答案 0 :(得分:3)

Cassandra不是一个数据库,你可以通过行键以外的任何东西进行查询。但您可以定制数据模型以支持这些查询。

我们每天在6个cassandra节点集群上执行175,000,000个查询(简单!)但我们只使用row_keys和列来请求数据,因为我们已经使数据模型以这种方式工作。我们不使用索引查询。

为了支持更丰富的查询,我们使用我们将用作搜索参数的数据来反规范化我们的数据,以便使密钥检索数据。

示例:考虑我们保存以下对象:

obj {
   id : xxx //assuming id is a unique id across the system
   p1 : value1
   p2 : value2
}

我们知道我们想要通过任何这些参数进行搜索,然后我们将保存obj的副本 对于column_names或键,如下所示:

"p1:value1:xxx"
"p2:value2:xxx"
"p1:value1:p2:value2:xxx" 
"xxx"

这样我们可以搜索obj,其中p1 = value1,p2 = value2,p1 = value1 AND p2 = value2或只是它的唯一id xxx。

如果您不想这样做,唯一的另一个选择是使用辅助索引和索引查询,但这会放弃您的问题的“无模式”要求。


<小时/> 编辑 - 一个例子。

我们希望保存定义为

的对象“产品”
class Products{
    string uid;
    string name;
    int screen_size; //in inches
    string os;
    string brand;
}

我们将它序列化为字符串或byteArray(我总是倾向于使用Jackson Json或Protobuf ......两者都能很好地与cassandra一起工作并且非常快)。 我们将该字节数组放入一列。

现在重要的部分:创建列名和行键。 假设我们希望按屏幕分辨率进行搜索,并可能按品牌进行过滤。 我们将屏幕大小的桶定义为[“0_to15”,“16_to_21”,“21_up”]

给定栏目:

"{uid:"MI615FMDO548", name:"SFG-0098", screen_size:15, os:"Android JellyBean", brand:"Samsung"}

保存一份副本: - key =“brand:Samsung”和column_name =“screen_size:15_uid:MI615FMDO548” - key =“brand:0_to_15”和column_name =“screen_size:15_uid:MI615FMDO548”

为什么要将uid添加到列名? 使所有列名称对于唯一产品都是唯一的。


示例第2部分现在我们假设已添加

"{uid:"MI615FMDO548", name:"SFG-0098", screen_size:15, os:"Android JellyBean", brand:"Samsung"}"
"{uid:"MI615FMD5589", name:"SFG-0097", screen_size:14, os:"Android JellyBean", brand:"Samsung"}"
"{uid:"MI615FMD1111", name:"SFG-0098", screen_size:17, os:"Android JellyBean", brand:"Samsung"}"
"{uid:"MI615FMDO687", name:"SFG-0095", screen_size:13, os:"Android JellyBean", brand:"Samsung"}"


我们最终会得到以下专栏系列:

Products{
-Row:"brand:Samsung"
=> "screen_size:13_uid:MI615FMDO687":"{uid:"MI615FMDO687", name:"SFG-0095", screen_size:13, os:"Android JellyBean", brand:"Samsung"}"
=> "screen_size:14_uid:MI615FMD5589":"{uid:"MI615FMD5589", name:"SFG-0097", screen_size:14, os:"Android JellyBean", brand:"Samsung"}
=> "screen_size:15_uid:MI615FMDO548":"{uid:"MI615FMDO548", name:"SFG-0098", screen_size:15, os:"Android JellyBean", brand:"Samsung"}"
=> "screen_size:17_uid:MI615FMD1111":"{uid:"MI615FMD1111", name:"SFG-0098", screen_size:17, os:"Android JellyBean", brand:"Samsung"}"
-Row:"screen_size:0_to_15"
=> "brand:Samsung_uid:MI615FMDO687":"{uid:"MI615FMDO687", name:"SFG-0095", screen_size:13, os:"Android JellyBean", brand:"Samsung"}"
=> "brand:Samsung_uid:MI615FMD5589":"{uid:"MI615FMD5589", name:"SFG-0097", screen_size:14, os:"Android JellyBean", brand:"Samsung"}
=> "brand:Samsung_uid:MI615FMDO548":"{uid:"MI615FMDO548", name:"SFG-0098", screen_size:15, os:"Android JellyBean", brand:"Samsung"}"
-Row:"screen_size:16_to_17"
=> "brand:Samsung_uid:MI615FMD1111":"{uid:"MI615FMD1111", name:"SFG-0098", screen_size:17, os:"Android JellyBean", brand:"Samsung"}"
-Row:"uid:MI615FMDO687"
=> "product":"{uid:"MI615FMDO687", name:"SFG-0095", screen_size:13, os:"Android JellyBean", brand:"Samsung"}"
-Row:"uid:MI615FMD5589"
=> "product":"{uid:"MI615FMD5589", name:"SFG-0097", screen_size:14, os:"Android JellyBean", brand:"Samsung"}
-Row:"uid:MI615FMDO548"
=> "product":"{uid:"MI615FMDO548", name:"SFG-0098", screen_size:15, os:"Android JellyBean", brand:"Samsung"}"
-Row:"uid:MI615FMD1111"
=> "product":"{uid:"MI615FMD1111", name:"SFG-0098", screen_size:17, os:"Android JellyBean", brand:"Samsung"}"
}

现在,通过跨列名称使用范围查询,您可以按品牌和屏幕尺寸进行搜索。


希望这很有用