Cassandra是一个开源的分布式数据库,结合了Dynamo的Key/Value与Bigtable的面向列的特点。
Cassandra 的特点如下:
1.灵活的schema:不需要象数据库一样预先设计schema,增加或者删除字段非常 方便(on the fly)。
2.支持range查询:可以对Key进行范围查询。
3.高可用,可扩展: 单点故障不影响集群服务,可线性扩展。
我们可以将Cassandra的数据模型想象成一个四维或者五维的 Hash。
Column
Column是Cassandra中最小的数据单元。它是一个3元的数据类型,包 含:name,value和timestamp。
将一个Column用JSON的形式表现出来如下:
1:
{ // 这是一个column
2:
name: "逖靖寒的世界"
,
3:
value: "gpcuster@gmali.com"
,
4:
timestamp: 123456789
5:
}
为了简单起见,我们可以忽略timestamp。就把column想象成一个name/value即可。
注意,这里提到的name和value都是byte[]类型的,长度不限。
SuperColumn
我们可以将SuperColumn想象成Column的数组,它包含一个name,以及一系列相应的Column。
将一个SuperColumn用JSON的形式表现如下:
1:
{ // 这是一个SuperColumn
2:
name: "逖靖寒的世界"
,
3:
// 包含一系列的Columns
4:
value: {
5:
street: {name: "street"
, value: "1234 x street"
, timestamp: 123456789},
6:
city: {name: "city"
, value: "san francisco"
, timestamp: 123456789},
7:
zip: {name: "zip"
, value: "94107"
, timestamp: 123456789},
8:
}
9:
}
Columns和SuperColumns都是name与value的组合。最大的不同在于Column的value是一个“string”,而 SuperColumn的value是Columns的Map。
还有一点需要注意的是:SuperColumn’本身是不包含timestamp的。
ColumnFamily
ColumnFamily是一个包含了许多Row的结构,你可以将它想象成RDBMS中的Table。
每一个Row都包含有client提供的Key以及和该Key关联的一系列Column。
我们可以看看结构:
1:
UserProfile = { // 这是一个ColumnFamily
2:
phatduckk: { // 这是对应ColumnFamily的key
3:
// 这是Key下对应的Column
4:
username: "gpcuster"
,
5:
email: "gpcuster@gmail.com"
,
6:
phone: "6666"
7:
}, // 第一个row结束
8:
ieure: { // 这是ColumnFamily的另一个key
9:
//这是另一个Key对应的column
10:
username: "pengguo"
,
11:
email: "pengguo@live.com"
,
12:
phone: "888"
13:
age: "66"
14:
},
15:
}
ColumnFamily的类型可以为Standard,也可以是Super类型。
我们刚刚看到的那个例子是一个Standard类型的ColumnFamily。Standard类型的ColumnFamily包含了一系列的 Columns(不是SuperColumn)。
Super类型的ColumnFamily包含了一系列的SuperColumn,但是并不能像SuperColumn那样包含一系列 Standard ColumnFamily。
这是一个简单的例子:
1:
AddressBook = { // 这是一个Super类型的ColumnFamily
2:
phatduckk: { // key
3:
friend1: {street: "8th street"
, zip: "90210"
, city: "Beverley Hills"
, state: "CA"
},
4:
John: {street: "Howard street"
, zip: "94404"
, city: "FC"
, state: "CA"
},
5:
Kim: {street: "X street"
, zip: "87876"
, city: "Balls"
, state: "VA"
},
6:
Tod: {street: "Jerry street"
, zip: "54556"
, city: "Cartoon"
, state: "CO"
},
7:
Bob: {street: "Q Blvd"
, zip: "24252"
, city: "Nowhere"
, state: "MN"
},
8:
...
9:
}, // row结束
10:
ieure: { // key
11:
joey: {street: "A ave"
, zip: "55485"
, city: "Hell"
, state: "NV"
},
12:
William: {street: "Armpit Dr"
, zip: "93301"
, city: "Bakersfield"
, state: "CA"
},
13:
},
14:
}
Keyspace
Keyspace是我们的数据最外层,你所有的ColumnFamily都属于某一个Keyspace。一般来说,我们的一个程序应用只会有一个 Keyspace。
简单测试
我们将Cassandra运行起来以后,启动命令行,执行如下操作:
cassandra> set Keyspace1.Standard1['jsmith']['first'] = 'John'
Value inserted.
cassandra> set Keyspace1.Standard1['jsmith']['last'] = 'Smith'
Value inserted.
cassandra> set Keyspace1.Standard1['jsmith']['age'] = '42'
Value inserted.
这个时候,Cassandra中就已经有3条数据了。
其中插入数据的各个字段含义如下:
set Keyspace1.Standard1['jsmith']['first'] = 'John'
/ / / / /
/ / /_ key / /_ value
/ / /_ column
/_ keyspace /_ column family
接下来,我们执行查询操作:
cassandra> get Keyspace1.Standard1['jsmith']
(column=age, value=42; timestamp=1249930062801)
(column=first, value=John; timestamp=1249930053103)
(column=last, value=Smith; timestamp=1249930058345)
Returned 3 rows.
这样,我们就可以将之前插入的数据查询出来了。