Cassandra – 理解关键概念和数据模型

Cassandra的设计理论倾向于实现CAP原则中的AP(Availability and Partition Tolerance)——高可用性和分布式,它的分布式是基于一致性哈希环(Consistent Hash Ring)算法实现的。 算法

面向行(Row-Oriented) 数据库

咱们经常说Cassandra是一个面向列(Column-Oriented)的数据库,其实这不彻底对——数据是以松散结构的多维哈希表存储在数据库中;所谓松散结构,是指每行数据能够有不一样的列结构,而在关系型数据中,同一张表的全部行必须有相同的列。在Cassandra中可使用一个惟一识别号访问行,因此咱们能够更好理解为,Cassandra是一个带索引的,面向行的存储。 数组

无结构(Schema Free) 服务器

Cassandra只须要你定义一个逻辑上的容器(Keyspaces)装载列族(Column Families),以后,你能够自由地向列族中添加数据。每个列族都被设计为一组数据关联或排列。这种结构意味着,根据你的需求场景,你能够只保存你须要的数据,而没必要拘泥于早前定义的表结构。 数据结构

适用场景(Use Cases for Cassandra) 并发

  • 快速开发应用程序:Schema Free的特色,让Cassandra能够快速适应你的初期变动;若是你使用关系型数据库,那么就不得不从数据表、DAO层、Logic/Service层到UI层进行层层变动,哪怕只是一个小小的列名或字段类型变化; 运维

  • 大量写入、统计和分析:Cassandra的列族设计是囊括数据关联和排序的,而且能够不存储不须要的数据,这极大减省了表联接和冗余字段带来的性能开销,后者偏偏是高并发写入操做、统计分析时关系型数据库的瓶颈; 分布式

  • 须要扩展的部署结构:Cassandra是面向分布式的设计,这让它能够灵活地水平扩展,以在运维阶段知足你的需求,而没必要考虑“将数据迁往更高性能的服务器”这样的问题。 ide

数据模型(Data Model) 高并发

咱们从最基本的概念来理解Cassandra的数据模型,先假设使用一个最简单的值结构来存放一堆数据(Values)。

Screen Shot 2013-11-30 at 6.50.59 PM

但问题是,除非咱们记录了每一个值的存放地址,咱们将没法访问到这些数据,这看起来很像一个数组或集合,咱们必须记住某个值的索引号,而且还要预先定义好这个数组的宽度,不然它会没法容纳足够多的数据。

解决办法是为每一个数据添加一个惟一名称(Name),只要咱们记住了这个名称,就能找到这个数据了,这样,咱们就有了一堆名称——值对(Name/Value Pair)。

Screen Shot 2013-11-30 at 6.58.27 PM

这个结构很像哈希表,能够知足一些信息的存储,例如用户的基本信息,姓、名、电话、手机、公司、地址等,而且咱们能够根据须要来决定存储哪些名称和值,如此,咱们就获得了一个单独的行(Single Row),并引出了Cassandra数据库中重要的行列概念定义:

一组包含名称值对的数据叫作行(Row),而每一组名称值对(Name/Value Pair)被称之为列(Column)。

Screen Shot 2013-11-30 at 7.11.01 PM

在关系型数据库中,列的名称必须是字符串,但在Cassandra中列名称能够为任意类型,这意味着,你能够将列名称也做为一个数据来存储。换一种说法,你没必要被数据类型约束,往Cassandra中添加数据就够了。

下面的示例可让咱们更好地理解Cassandra的数据存储:

Musician:                           ColumnFamily 1 
    bootsy:                         RowKey 
        email: bootsy@pfunk.com,    ColumnName:Value 
        instrument: bass            ColumnName:Value 
    george:                         RowKey 
        email: george@pfunk.com     ColumnName:Value
Band:                               ColumnFamily 2 
    george:                         RowKey 
        pfunk: 1968-2010            ColumnName:Value

另外,Cassandra还有一种可在列之间创建关联的超级列(Super Column),你能够往超级列中添加子列。

Screen Shot 2013-11-30 at 7.17.58 PM

键空间(Keyspaces)

键空间是Cassandra的数据容器,能够理解为关系型数据库中的数据库(Database)。对于一个Keyspace来讲,有如下几个属性:

  • 数据复制节点数目(Replication factor ):定义Keyspace中每行数据的复制节点数目,若是定义为三,在哈希环上,每行数据将会有三个拷贝节点,而且都可以被客户端请求到。

  • 复制替换策略(Replica placement strategy):定义在一致性哈希环中某个节点的替换策略。

  • 列族(Column Families):相似于关系型数据库中的表(Table),是列的容器。

列族(Column Families)

上面已经讲到,列族是列的容器,它的结构像是一个四维哈希表:

[Keyspace][ColumnFamily][Key][Column]

若是用JSON表示,一组存放在列族中的数据看起来是这样的:

Hotel {
    key: AZC_043 { name: Cambria Suites Hayden, phone: 480-444-4444,address: 400 N. Hayden Rd., city: Scottsdale, state: AZ, zip: 85255} 
    key: AZS_011 { name: Clarion Scottsdale Peak, phone: 480-333-3333,address: 3000 N. Scottsdale Rd, city: Scottsdale, state: AZ, zip: 85255} 
    key: CAS_021 { name: W Hotel, phone: 415-222-2222,address: 181 3rd Street, city: San Francisco, state: CA, zip: 94103} 
    key: NYN_042 { name: Waldorf Hotel, phone: 212-555-5555,address: 301 Park Ave, city: New York, state: NY, zip: 10019} }

使用Cassandra建立键空间Hotelier,列族为Hotel,并查询行键(Row Key)为“NYN_042”的结果显示:

cassandra> get Hotelier.Hotel['NYN_042']
=> (column=zip, value=10019, timestamp=3894166157031651)
=> (column=state, value=NY, timestamp=3894166157031651)
=> (column=phone, value=212-555-5555, timestamp=3894166157031651)
=> (column=name, value=The Waldorf=Astoria, timestamp=3894166157031651) 
=> (column=city, value=New York, timestamp=3894166157031651)

列(Column)

若是你对“列”的理解来自于关系型数据库,那么很容易产生和我以前同样的误解,觉得Cassandra是把关系型数据库的行列进行了某种倒置而获得的设计。其实不是这样的,Cassandra的列是一组键值对,它的结构以下图所示(事实上,这个数据结构是Cassandra 0.7.0,最新的2.0.3版本中ByteBuffer替代了byte[],long型的日期时间替代了IClock):

Screen Shot 2013-11-30 at 7.45.30 PM

使用JSON描述的列结构:

{
    "name": "email",
    "value: "me@example.com", 
    "timestamp": 1274654183103300
}

超级列(Super Column)的结构:

Screen Shot 2013-11-30 at 7.55.14 PM

复合键(Composite Keys)

有时咱们会遇到不一样省份可能有一样的城市名称,或不一样的城市有重名的街道,这时使用单一的城市名称或街道名称来做为Key就会没法识别。Cassandra容许你使用Key1:Key2的结构来存储一对值做为Key,一个常见的例子是使用<userid:lastupdate>这样的结构来存储用户ID及最后登陆时间。下面是一个例子:

HotelByCity (CF) Key: city:state {
    key: Phoenix:AZ {AZC_043: -, AZS_011: -} 
    key: San Francisco:CA {CAS_021: -}
    key: New York:NY {NYN_042: -}
}

最后让咱们来巩固一下Cassandra和关系型数据库的区别吧:

  • 没有查询语言:No SQL (Structured Query Language);

  • 没有外键约束:关系型数据库的最重要特征;

  • 双重簇索引:在关系型数据库中,每一个表只能指定一个簇索引,其它的索引查询都会致使全表扫描,但在Cassandra中,咱们能够有第二级的簇索引;

  • 排序是在设计时决策:Cassandra不支持Order By,排序是须要设计时考虑,而不是像在关系型数据库查询时刻使用Order By;

  • 无数据结构约定:这是Cassandra最大的优点,在关系型数据库中,咱们设计数据库结构时老是慎之又慎,但在Cassandra中不须要预先约定数据结构。

本文参考自《Cassandra: The Definitive Guide》

原文连接:Cassandra – 理解关键概念和数据模型

相关文章
相关标签/搜索