Cassandra数据模型

来源:互联网 发布:域名管理网站 编辑:程序博客网 时间:2024/04/29 12:18

Cassandra数据模型

译者:陆志忠  原文:http://wiki.apache.org/cassandra/DataModel

 

介绍

Cassandra数据模型是通过四维或五维Hash实现的

其基本组成:

 

Cluster:机器(节点)在一个逻辑Cassandra实例。Clusters能够包含多个keyspaces。

Keyspace: ColumnFamilies命名空间,通常每个应用有一个。

ColumnFamilies包含多个Column,每个Column有名字,值和时间戳,它被每行(Row)的Key应用。

SuperColumns也是一种Column,本身有很多子Column。

 

我们将从下到上开始讲,即从树的叶子节点(Cassandra的数据结构(column))往上到树的根结点(Cluster)

 

Columns

 

Column是系统中增加的数据最小的单位,它包含三部分:name, value和timestamp

 

下面是一个简单的Column接口(注:结构)定义

 

struct Column{

1:binary  name,

2:binary  value,

3:i64       timestamp,

}

 

JSON数据的表示方式:

 

{

"name":"emailAddress",

"value":"lzz313atgmail.com",

"timestamp":12345678

}

 

所有的值都是由client提供,包含‘timestamp'. 这就意味着client端的时钟应该被同步(在Cassandra服务器端同步也是非常有用的),这里的时间戳(timestamp)是用来解决冲突的。 在客户端的很多情况下‘timestamp’是不会被使用的,根据时间戳能方便的找到Column的name/value。

在文档的剩下部分,‘timestamps'将被省略,另外name和value是二进制值,在许多应用程序中把他们序列化为UTF-8的字符串。

 

Timestamps能够做你任何想做的事,是一个从1970开始的毫秒数,在Java中使用System.getTimeMillis()方法获得。无论你什么时候使用,它必须在交叉的应用中一致否则可能之前改变的可能覆盖最新的。

 

Column Families

一个Column Family是很多Column的容器(注:集合),类似关系系统中的表(table)。可以在你的storage-conf.xml文件中定义column families,且在Cassandra进程没有重新启动的情况下不能改变他们(或添加一个新的Column Families)。 Column family是一个column的有序列表,是通过name来排序的。

 

Column families每行上的列都可以应用一个可配置的排序,它会影响调用了get_slice的thrift API。ASCII,UTF-8,Long 和UUID(词汇和时间)上可以实现开箱即用的排序。

 

Rows

在Cassandra系统中,每个column family被存储在不同的文件里,这些文件是按照row上的主要order(注:主要的排序键)(i.e. key)来排序的。相关的columns中你将一起访问,应该被保存在相同的column family中。

 

Row的key是决定了存储在机器上的数据。因此你可以根据每个key从多个与之相关column families上获取到数据。但是这些在逻辑上来说是不同的,这就是为什么thrift interface获取数据的时候在同一个时间里每个key只有一个column family。(TODO given this, is the following JSON more confusing than helpful?)

 

JSON表示key -> column families -> column structure 

 

 

{   "mccv":{      "Users":{         "emailAddress":{"name":"emailAddress", "value":"lzz313atgmail.com"},         "webSite":{"name":"webSite", "value":"http://blog.csdn.net/lzz313"}
}, "Stats":{ "visits":{"name":"visits", "value":"243"} } }, "user2":{ "Users":{ "emailAddress":{"name":"emailAddress", "value":"10061@hipicube.com"}, "twitter":{"name":"hipikids", "value":"10061"} } }}

 

注意“mccv”的关键数据在两个不同column families里面,“Users"和“Stats".这并不意味着数据和这些column families相关。相同的key在不同的column families取决于应用程序。另外要注意的是有“Users” column family,“mccv”和“user2”有被定义为不同的column名字。这在Cassandra系统中是完全有效的。事实上这儿可以定义有许多虚拟的无限制的column名字,从而导致很多在用普通的column名字作为一个运行时的数据块。这是一个不寻常的存储系统,特别是对一直在使用RDBMS系统的人来说。

 

Keyspaces

 

Keyspace是Cassandra第一维hash,是column families的容器(container)。Keyspaces和RDBMS系统中的schema或database(i.e 一个逻辑集合的tables)有几乎相同的粒度。他们可以对column families进行配置和管理,也是一种可以用于批量insert的结构(structure).

 

Super Columns

 

到现在为止,我们已讲了正常的 columns和rows。Cassandra 也支持超级columns(super columns):columns的值也可以是超级columns;一个超级column是由一个(已排序)的数组构成。

 

因此我们想到columns和super columns在map上:row在普通的column family是基本上是一个已排序的column名字到column值的map;row在一个super column family是一个已排序的super column map,这个super column也是一个已排序的column名字到column值的map。

 

 

 

JSON描述:

 

{  "mccv": {    "Tags": {      "cassandra": {        "incubator": {"incubator": "http://www.hipikids.com"},        "hipikids": {"hipicube": "http://hipicd.hipicube.com"}      },      "thrift": {        "hipikids": {"hipicube": "http://hipicd.hipicube.com"}      }    }    }}

这儿我的column family是“Tags”。我定义了两个super columns:“cassandra"和“thrift"。 这些特定的命名的bookmarks中每个都是一个column。

就像普通的column,超级column是稀疏(sparse):每行(row)包含尽可能多或尽可能少;Cassandra并没有限制。

 

范围查询(Range queries)

Cassandra可以用相对少量的代码支持可插入分区(partitioning scheme)。开箱即用,Cassandra提供基于hash的RandomPartitioner和OrderPreservingPartitioner。

RandomPartitioner 提供了不错的负载均衡,另一方面OrderPreservingPartitioner让你可以在所存储的key的某一范围内查询,但是需要仔细的选择节点或主动做负载均衡。

对于仅支持基于hash的分区不支持高效率的范围查询,

 

Modeling your application不像关系系统,你的model实体和实体之间关系通过添加索引来支持一切有必要的查询,在Cassandra系统中你必要想一下支持有效率的查询的适当的model,由于没有自动索引,你的每个查询应该比关系查询中的表会更接近于columnfamily,不要害怕反模式;Cassandra比关系系统中的写操作快很多很多。Arin Sarkissian的Digg中有一篇非常优秀的Cassandra's data model并且详细举例说明。当你设计model的时候要参考CassandraLimitations例子:SuperColumns for Search Apps你可以把每个super column名字想像为一个词语(term),它包含一个docId,等级信息,和其他属性。如果你用userid作为key,这时你可以以这种形式为每个用户的存储索引。这就是Facebook怎样从Inbox通过索引找出每个用户方法。此外,存储数据在磁盘上按“Time”排序的,系统可以很容易的查处“给我10个最新的消息”。有关图解请参考在SIGMOD 2008的Cassandra ppt。Example:multiuser blogTODOThrift API移到 API。Attribution感谢phatduckk和asenchi对于例子,文字的审查。

 

 

原创粉丝点击