Cassandra介绍和一些常用操作

Cassandra是一个高可靠的大规模分布式存储系统。高度可伸缩的、一致的、分布式的结构化key-value存储方案,集Google BigTable的数据模型与Amazon Dynamo的完全分布式的架构于一身。Cassandra使用了Google BigTable的数据模型,与面向行的传统的关系型数据库不同,这是一种面向列的数据库,列被组织成为列族(Column Family),在数据库增加一列非常方便。Cassandra的系统架构与Dynamo一脉相承,是基于O(1)DHT(分布式哈希表)的完全P2P架构,与传统的基于Sharding的数据库集群相比,Cassandra可以无缝地加入或删除节点,非常适于对于节点规模变化比较快的应用场景。

Cassandra的数据会写入多个节点,来保证数据的可靠性,在一致性、可用性和网络分区耐受能力(CAP)的折衷问题上,Cassandra比较灵活,用户在读取时可以指定要求所有副本一致(高一致性)、读到一个副本即可(高可用性)或是通过选举来确认多数副本一致即可(折衷)。这样,Cassandra可以适用于有节点、网络失效,以及多数据中心的场景。Cassandra是一套开源分布式Nosql数据库系统,设计思想采用了google的BigTable的数据模型和Amazon的Dynamo的完全分布式架构,因而它具有很好的扩展性且不存在单点故障。

Hadoop HBase
Hadoop HBase是Apache Hadoop项目的一个子项目,是Google BigTable的一个克隆,与Cassandra一样,它们都使用了BigTable的列族式的数据模型,两者的主要不同在于:
(1) Cassandra只有一种节点,而HBase有多种不同角色,又架构在Hadoop底层平台之上,部署上Cassandra更简单;
(2) Cassandra的数据一致性策略是可配置的;
(3) HBase提供了Cassandra没有的行锁机制,Cassandra要想使用锁需要配合其他系统,如Hadoop Zookeeper;
(4) HBase提供更好的MapReduce并行计算支持,Cassandra在0.6版本也提供了这个功能
(5) Cassandra的读写性能和可扩展性更好,但不擅长区间扫描。

Nosql数据库是为高扩展性系统设计的,采用了key/value模型,但它的缺点,正如Nosql这个名字表明地那样,不支持sql操作。这听起来像是一个很严重的缺陷。下面介绍一些在sql中常见的操作怎样在cassandra中自然而又有效的实现。

0.示例column family

表1:

CREATE TABLE example ( id int,name ascii,age bigint,gender bigint,high varint,PRIMARY KEY (id,name,age) ) WITH CLUSTERING ORDER BY (name ASC,age ASC) AND bloom_filter_fp_chance = 0.1 AND caching = '{"keys":"ALL","rows_per_partition":"NONE"}' AND comment = '' AND compaction = {'class': 'org.apache.cassandra.db.compaction.LeveledCompactionStrategy'} AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'} AND dclocal_read_repair_chance = 0.1 AND default_time_to_live = 86400 AND gc_grace_seconds = 86400 AND max_index_interval = 2048 AND memtable_flush_period_in_ms = 0 AND min_index_interval = 128 AND read_repair_chance = 0.0 AND speculative_retry = '99.0percentile';

表1内容

 id | name | age | gender | high ----+------+-----+--------+------
 5 | ee | 25 | 1 | 168
 1 | aa | 10 | 1 | 165
 2 | bb | 20 | 0 | 170
 4 | dd | 40 | 0 | 190
 6 | ff | 30 | 0 | 168
 3 | cc | 30 | 1 | 180

表2:

CREATE TABLE test ( id int,PRIMARY KEY ((id,name),age) ) WITH CLUSTERING ORDER BY (age ASC) AND bloom_filter_fp_chance = 0.1 AND caching = '{"keys":"ALL","rows_per_partition":"NONE"}' AND comment = '' AND compaction = {'class': 'org.apache.cassandra.db.compaction.LeveledCompactionStrategy'} AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'} AND dclocal_read_repair_chance = 0.1 AND default_time_to_live = 86400 AND gc_grace_seconds = 86400 AND max_index_interval = 2048 AND memtable_flush_period_in_ms = 0 AND min_index_interval = 128 AND read_repair_chance = 0.0 AND speculative_retry = '99.0percentile';

表2内容

 id | name | age | gender | high ----+------+-----+--------+------
 1 | aa | 10 | 1 | 165
 6 | ff | 30 | 0 | 168
 4 | dd | 40 | 0 | 190
 3 | cc | 30 | 1 | 180
 5 | ee | 25 | 1 | 168
 2 | bb | 20 | 0 | 170

1.查询

在example表,id是分区主键,(name,age)是排序主键
在test表,(id,name)是分区主键,age是排序主键
在example表,查询可以如下

select * from example where id = 1;
select * from example where id = 1 and name = ''aa";
select * from example name = ''aa" allow filtering;
select * from example name > ''aa" allow filtering;
select * from example age = 30 allow filtering; ----X
select * from test where id = 3;  ---X
select * from test where age > 20 allow filtering;

如果使用分区主键查询的话,需要指定全部的分区主键,不能使用部分分区主键查询
对于排序主键,可以使用>,<,>=,<=来查询,如果前面有分区主键,可以直接用。如果只使用排序主键来查询的话,只能使用排序主键的第一个查询,并且使用allow filtering;或者使用排序主键的第一个、第二个一起来查询,就是说要排序主键要有第一个才能使用第二个,有第二个才能使用第三个。但是这样会全表扫描,严重影响性能

2.创建二级索引

如果我们想直接查example表的age和test表的name了么?
方法是有的,那就是建索引:

CREATE INDEX ON example(age);
CREATE INDEX ON test(name);

我们就能在desc example和desc test的时候看到下面的语句了:

desc example:
CREATE INDEX example_age_idx ON ad.example (age);
desc test:
CREATE INDEX test_name_idx ON ad.test (name);

但是建的二级索引只能支持=查询不支持范围查询

3.分页查询

1,2.x的api里面有支持分页查询
2,手动分页查询可以使用token,下面的例子使用认排序。

cqlsh:> select * from example limit 2;

 id | name | age | gender | high ----+------+-----+--------+------
 5 | ee | 25 | 1 | 168
 1 | aa | 10 | 1 | 165

(2 rows)
cqlsh:> select * from example where token(id) > token(1) limit 2;

 id | name | age | gender | high ----+------+-----+--------+------
 2 | bb | 20 | 0 | 170
 4 | dd | 40 | 0 | 190

(2 rows)
cqlsh:> select * from example where token(id) > token(4) limit 2;

 id | name | age | gender | high ----+------+-----+--------+------
 6 | ff | 30 | 0 | 168
 3 | cc | 30 | 1 | 180

4.复杂Select

从现在起考虑一个基本的例子:存在一对多关系的department和employee。我们需要两个Column Family(简称“CF”):Emps和Deps。在Emps中,employee ID作为key,employee的name,birthday和city作为column;在Deps中,department ID作为key,department name作为column。

如果查询select * from Emps where Birthdate = ’25/04/1975′为了支持查询,我们需要添加一个Birthdate_Emps的CF,其中date为key, name为出生在该天的employee的ID,value可以是一个空的byte数组(用“-”代替)。每当从/向 Emps中插入 /删除employee信息时,我们需要同时更新Birthdate_Emps。为了执行该查询,我们只需从Birthdate_Emps中检索出key ’25/04/1975′对应的所有column。

注意,Birthdate_Emps实际上是一个帮助我们快速执行查询的索引,且这个索引有很强的可扩展性,因为它是分布到各个cassandra节点上的。你可以通过在Birthdate_Emps中添加employee冗余信息的方法进一步加速查询速度,这时,employee的ID变成了super column的名字,employee的所有column变成了该super column的column。

5.Join

查询select * from Emps e,Deps d where e.dep_id = d.dep_id
Join实际上是要建立不同实体之间的联系。这种联系可以很容易地通过迭代表示出来。为了实现该查询,可以添加一个叫Dep_Emps的CF,其中department ID作为key,与之对应的employee的ID为name。

6.Group By

例如查询select count(*) from Emps group by City
从实现角度看,Group By类似于上面描述的select/indexing,你只需要添加一个叫City_Emps的CF,其中,city作为key,employee的ID作为column name。当执行查询的时候,你只需计算需检索的city对应的employee数目或者专门添加一个column记录该数目。

7.Order By

为了支持排序操作,你可以使用OrderPreservingPartitioner对数据按照key进行排序。具体可参见:Cassandra: RandomPartitioner vs OrderPreservingPartitioner

为了支持4-7的这些操作,我们针对查询存储了冗余数据,这样做意味着:
(1) 必须事先知道系统中需要哪些query(不支持即时查询)。幸运的是,典型的web应用和企业OLTP应用的查询均是事先知道的,且数目不多,不经常改动,具体可阅读这篇论文:The End of an Architectural Era
(2) 我们将压力从查询转移到更新,这是为了支持物化视图(提前计算出查询结果)。这样做,对于Cassandra是非常有意义的,因为Cassandra的更新操作是经过优化的(多亏了最终一致性和从google的BigTable借鉴的“log-structured”存储理念),并且相比于pull-on-demand模型,cassandra的使用场景更适合push-on-change 模型。关于pull-on-demand和push-on-change模型,可参考文章Why are Facebook,Digg,and Twitter so hard to scale?

参考文章

  1. 董的博客Cassandra中实现SQL操作

相关文章

校园网上订餐系统系统主要功能模块包括公告内容(公告栏、轮...
从今天开始,正式进入项目阶段。本次的项目是跟着黑马的瑞吉...
在可预见的将来,IT不会萎缩,只会越发展越庞大,最终会渗透...
vulntarget-b靶场最详细通关记录。
MongoDB是一个开源、高性能、支持海量数据存储的。
【NoSQL数据库技术与应用】课本代码、课后答案(持续更新)