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

Aba*_*h A 7 cassandra

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

  1. 每行具有可变列数的无架构数据库.
  2. 数以万计的记录和数十列.
  3. 每天数百万次查询.
  4. 每天有数千人写作.
  5. 查询将过滤几个列(不仅是键).

我正在考虑按比例建造的Cassandra.

我的问题是:

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

编辑

我想确保我的观点是正确的.所以,下面的例子说明了我从你的答案得到的:

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

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"}
}
Run Code Online (Sandbox Code Playgroud)

并且,我们要添加"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"}
}
Run Code Online (Sandbox Code Playgroud)

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

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"}
}
Run Code Online (Sandbox Code Playgroud)

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

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


另一点:我无法确切地看到为什么创建二级索引会放弃或剥夺无模式模型.

le-*_*ude 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
}
Run Code Online (Sandbox Code Playgroud)

我们知道我们想要通过这些参数中的任何一个进行搜索,那么我们将为 column_names 或键保存 obj 的副本,如下所示:

"p1:value1:xxx"
"p2:value2:xxx"
"p1:value1:p2:value2:xxx" 
"xxx"
Run Code Online (Sandbox Code Playgroud)

这样我们就可以用 p1 = value1、p2 =value2、p1 = value1 AND p2 = value2 或仅通过它的唯一 id xxx 来搜索 obj。

如果您不想这样做,唯一的其他选择是使用二级索引和索引查询,但这将放弃您的问题的“无架构”要求。



编辑-一个例子。

我们想要保存对象“产品”定义为

class Products{
    string uid;
    string name;
    int screen_size; //in inches
    string os;
    string brand;
}
Run Code Online (Sandbox Code Playgroud)

我们将其序列化为字符串或 byteArray(我总是倾向于使用 Jackson Json 或 Protobuf ...两者都可以很好地与 cassandra 配合使用,并且速度非常快)。我们将该字节数组放入一列中。

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

给定列:

class Products{
    string uid;
    string name;
    int screen_size; //in inches
    string os;
    string brand;
}
Run Code Online (Sandbox Code Playgroud)

保存一份副本: - 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"}
Run Code Online (Sandbox Code Playgroud)


我们最终将得到以下列族:

"{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"}"
Run Code Online (Sandbox Code Playgroud)

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



希望这有用