Cassandra数据模型

提起NoSQL 这个话题,仿佛不应该是DBA 要关注的事,而是架构师应该关心的。但是作为一名DBA ,在使用传统的关系型思想建模时,应该有必要了解NoSQL 的建模方法。

各种NoSQL 数据库有很多,我最关注的还是BigTable 类型,因为它是一个高可用可扩展的分布式计算平台,用来处理海量的结构化数据,而数据库同样也是处理结构化数据,所以除了没有SQL ,在数据模型方面有相似之处。Cassandra facebook 开源出来的一个版本,可以认为是BigTable 的一个开源版本,目前twitterdigg.com 在使用。我们尝试从DBA 的角度出发去理解Cassandra 的数据模型。

NoSQL 并不能简单的理解为No SQL ,其本质应该是No Relational , 也就是说它不是基于关系型的理论基础,而我们所有传统的数据库都是基于这套理论而发展起来的,所以SQL 并不是问题的关键所在,比如有些NoSQL 数据库 可以提供SQL 类型的接口,允许你通过类SQL 的语法去访问数据。而Friendfeed 则是反其道而行之,利用关系型数据库MySQL ,采用了去关系化 的设计方法,去实现自己的KeyValue 存储。所以NoSQL 的本质是No Relational.

Cassandra 特点:

1. 灵活的schema ,不需要象数据库一样预先设计schema ,增加或者删除字段非常方便(on the fly )。

2. 支持range 查询:可以对Key 进行范围查询。

3. 高可用,可扩展:单点故障不影响集群服务,可线性扩展。

Keyspace

Cassandra 中的最大组织单元,里面包含了一系列Column familyKeyspace 一般是应用程序的名称。你可以把它理解为Oracle 里面的一个schema ,包含了一系列的对象。

Column family CF

CF 是某个特定Key 的数据集合,每个CF 物理上被存放在单独的文件中。从概念上看,CF 有点象数据库中的Table.

Key

数据必须通过Key 来访问,Cassandra 允许范围查询,例如:start => '10050', :finish => '10070'

Column

Cassandra 中字段是最小的数据单元,columnvalue 构成一个对,比如:name:“jacky”columnnamevaluejacky ,每个column:value 后都有一个时间戳:timestamp

和数据库不同的是,Cassandra 的一行中可以有任意多个column ,而且每行的column 可以是不同的。从数据库设计的角度,你可以理解 为表上有两个字段,第一个是Key ,第二个是长文本类型,用来存放很多的column 。这也是为什么说Cassandra 具备非常灵活schema 的原 因。

Super column

Super column 是一种特殊的column ,里面可以存放任意多个普通的column 。而且一个CF 中同样可以有任意多个Super column ,一个CF 只能定义使用Column 或者Super column ,不能混用。下面是Super column 的一个例子,homeAddress 这个Super column 有三个字段:分别是streetcityzip

homeAddress: {street: "binjiang road",city: "hangzhou",zip: "310052",}

Sorting

不同于数据库可以通过Order by 定义排序规则,Cassandra 取出的数据顺序是总是一定的,数据保存时已经按照定义的规则存放,所以取出来的顺序已经确定了,这是一个巨大的性能优势。有意思的是,Cassandra 按照column name 而不是column value 来进行排序, 它 定义了以下几种选项:BytesType, UTF8Type, LexicalUUIDType, TimeUUIDType, AsciiType,  LongType ,用来定义如何按照column name 来排序。实际上,就是把column name 识别成为不同的类型,以此来达到灵活排序的目的。UTF8Type 是把column name 转换为UTF8 编码来进行排序,LongType 转换成为64long 型,TimeUUIDType 是按照基于时间的UUID 来排序。例如:

Column name 按照LongType 排序:

{name: 3, value: "jacky"},
{name: 123, value: "hellodba"},
{name: 976, value: "Cassandra"},
{name: 832416, value: "bigtable"}

Column name 按照UTF8Type 排序:

{name: 123, value: "hellodba"},
{name: 3, value: "jacky"},
{name: 832416, value: "bigtable"}
{name: 976, value: "Cassandra"}

下面我们看twitterSchema

<Keyspace Name="Twitter">
  
<ColumnFamily CompareWith="UTF8Type" Name="Statuses" />
  
<ColumnFamily CompareWith="UTF8Type" Name="StatusAudits" />
  
<ColumnFamily CompareWith="UTF8Type" Name="StatusRelationships"
    
CompareSubcolumnsWith="TimeUUIDType" ColumnType="Super" />
  
<ColumnFamily CompareWith="UTF8Type" Name="Users" />
  
<ColumnFamily CompareWith="UTF8Type" Name="UserRelationships"
    
CompareSubcolumnsWith="TimeUUIDType" ColumnType="Super" />
</Keyspace>

我们看到一个叫Twitterkeyspace ,包含若干个CF ,其中StatusRelationships UserRelationships 被定义为包含Super columnCFCompareWith 定义了column 的排序规则,CompareSubcolumnsWith 定义了subcolumn 的排序 规则,这里使用了两种:TimeUUIDTypeUTF8Type 。我们没有看到任何有关column 的定义,这意味着column 是可以灵活变更的。

为了方便大家理解,我会尝试着用关系型数据库的建模方法去描述TwitterSchema ,但千万不要误认为这就是Cassandra 的数据模型 ,对于Cassandra 来说,每一行的colunn 都可以是任意的,而不是象数据库一样需要在建表时就创建好。

Users CF 记录用户的信息,Statuses CF 记录tweets 的内容,StatusRelationships CF 记录用户看到的tweetsUserRelationships CF 记录用户看到的followers 。我们注意到排序方式是TimeUUIDType ,这个类型是按照时间进行排序的UUID 字段,column name 是用UUID 函数产生(这个函数返回了一个UUID ,这个UUID 反映了当前的时间,可以根据这个UUID 来排序,有点类似于timestamp 一样),所以得到结果是按照时间来排序的。使用过twitter 的人都知道,你总是可以看到自己最新的tweets 或者最新的friends.

存储

Cassandra 是基于列存储的(Bigtable 也是一样) ,这个和基于列的数据库是一个道理。

API

下面是数据库,BigtableCassandra API 的对比:

Relational                     
SELECT `column` FROM `database`.`table` WHERE `id` = key;
BigTable                       
table.get(key, "column_family:column")
Cassandra: standard model      
keyspace.get("column_family", key, "column")
Cassandra: super column model  
keyspace.get("column_family", key, "super_column", "column")

我对Cassandra 数据模型的理解:

1.column name 存放真正的值,而value 是空。因为Cassandra 是按照column name 排序,而且是按列存储的,所以往往利用column name 存放真正的值,而value 部分则是空。例如:“jacky”:“null”“fenng”:”null”

2.Super column 可以看作是一个索引,有点象关系型数据库中的外键,利用super column 可以实现快速定位,因为它可以返回一堆column ,而且是排好序的。

3. 排序在定义时就确定了,取出的数据肯定是按照确定的顺序排列的,这是一个巨大的性能优势。

4. 非常灵活的schemacolumn 可以灵活定义。实际上,colume name 在很多情况下,就是value (是不是有点绕)。

5. 每个column 后面的timestamp ,我并没有找到明确的说明,我猜测可能是数据多版本,或者是底层清理数据时需要的信息。

最后说说架构,我认为架构的核心就是有所取舍 ,不管是CAP 还是BASE ,讲的都是这个原则。架构之美在于没有任何一种架构可以完美的解决各种问题,数据库和NoSQL 都有其应用场景,我们要做的就是为自己找到合适的架构。

–EOF–

这篇文章,我参考了up and running with cassandra ,除此以外,我还参考了twitter 提供的API ,它帮助我理解twitterschema 设计。这篇文章,肯定有很多理解不正确的地方,希望朋友们指正。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值