6.4 R利剑NoSQL之Cassandra
问题
R如何连接Cassandra?
引言
Cassandra是由Facebook开发,然后开源的一套分步式数据存储系统,用于海量数据的高伸展性存储。Cassandra的无中心设计、一致性哈希、BloomFilter等技术为之后的NoSQL产品提供新的设计思路。本节将介绍RCassandra,让R程序轻松连接Cassandra。
6.4.1 Cassandra环境准备
Cassandra 的名称来源于希腊神话,是特洛伊的一位悲剧性的女先知的名字,因此项目的Logo是一只放光的眼睛。Cassandra的数据会写入多个节点,来保证数据的可靠性,在一致性、可用性和网络分区耐受能力(CAP)的折衷问题上,Cassandra比较灵活,用户在读取时可以指定要求所有副本一致(高一致性)、读到一个副本即可(高可用性)或是通过选举来确认多数副本一致即可(折衷)。这样,Cassandra可以适用于有节点、网络失效以及多数据中心的场景。
先是环境准备,这里我选择了Linux Ubuntu操作系统,大家可以根据自己的使用习惯选择顺手的Linux。Cassandra服务器环境是:
- Linux Ubuntu 12.04.2 LTS 64bit server
- Java JDK 1.6.0_45
- Cassandra 1.2.15
关于Cassandra的安装和配置,请参考附录E。
启动Cassandra服务器,使用bin/cassandra命令。
~cd /home/conan/tookit/cassandra1215 # 进入cassandra安装目录
~ bin/cassandra # 启动cassandra
~ ps -aux|grep cassandra # 查看系统进程
~ cat /var/log/cassandra/system.log |less # 查看启动日志
INFO [main] 2014-03-22 06:28:08,777 CassandraDaemon.java (line 119) Logging initialized
INFO [main] 2014-03-22 06:28:08,795 CassandraDaemon.java (line 144) JVM vendor/version: Java HotSpot(TM) 64-Bit Server VM/1.6.0_45
INFO [main] 2014-03-22 06:28:08,799 CassandraDaemon.java (line 182) Heap size: 2051014656/2051014656
6.4.2 RCassandra函数库
RCassandra支持的函数只有17个。前面介绍过rredis有100个函数,rmongodb有153个函数,相比之下RCassandra的函数是比较少的。但是这17个函数,并没有覆盖Cassandra的所有操作,就连一些基本的操作都没有函数支持,要在命令行处理,不知道是什么原因。希望RCassandra能继续发展,完善没有实现的功能函数。
1. 17个函数
下面列出了这17个函数,并与Cassandra的命令做了对比说明。
RC.close RC.insert
RC.cluster.name RC.login
RC.connect RC.mget.range
RC.consistency RC.mutate
RC.describe.keyspace RC.read.table
RC.describe.keyspaces RC.use
RC.get RC.version
RC.get.range RC.write.table
RC.get.range.slices
2. Cassandra和RCassandra的基本操作对比:
#连接到集群
Cassandra:
connect 192.168.1.200/9160;
RCassandra:
conn<-RC.connect(host="192.168.1.200",port=9160)
#查看当前集群名字
Cassandra:
show cluster name;
RCassandra:
RC.cluster.name(conn)
#列出当前集群所有keyspaces
Cassandra:
show keyspaces;
RCassandra:
RC.describe.keyspaces(conn)
#查看DEMO的keyspace
Cassandra:
show schema DEMO;
RCassandra:
RC.describe.keyspace(conn,'DEMO')
#选择DEMO的keyspace
Cassandra:
use DEMO;
RCassandra:
RC.use(conn,'DEMO')
#设置一致性级别
Cassandra:
consistencylevel as ONE;
RCassandra:
RC.consistency(conn,level="one")
#插入数据
Cassandra:
set Users[1][name] = scott;
RCassandra:
RC.insert(conn,'Users','1', 'name', 'scott')
#插入数据框
Cassandra:
NA
RCassandra:
RC.write.table(conn, "Users", df)
#读取列族所有数据
Cassandra:
list Users;
RCassandra:
RC.read.table(conn,"Users")
#读取数据
Cassandra:
get Users[1]['name'];
RCassandra:
RC.get(conn,'Users','1', c('name'))
#退出连接
Cassandra:
exit; quit;
RCassandra:
RC.close(conn)
6.4.3 RCassandra基本使用操作
我们使用RCassandra进行基本的函数操作,以R语言中iris的数据集为例,介绍如何利用RCassandra操作Cassandra数据库。使用R语言的RCassandra客户端远程访问Cassandra服务器进行测试。
客户端环境
- Linux: Ubuntu 12.04.2 LTS 64bit server
- R: 3.0.1, x86_64-pc-linux-gnu (64-bit)
首先,启动R程序,安装RCassandra包。
~ R # 启动R程序
> install.packages('RCassandra') #安装RCassandra
> library(RCassandra) #加载RCassandra类库
建立服务器连接
> conn<-RC.connect(host="192.168.1.200") #建立服务器连接
> RC.cluster.name(conn) #当前集群的名字(2个节点集群的名字)
[1] "case1"
> RC.version(conn) #当前协议的版本
[1] "19.36.0"
keyspaces的操作
> RC.describe.keyspaces(conn) #列出所有keyspaces配置信息
> RC.describe.keyspace(conn, "DEMO") #列出叫的DEMO的keyspaces配置信息
数据的操作
#RCassandra是不能创建的列族的,提前通过Cassandra命令创建一个列族
#[default@DEMO] create column family iris;
> head(iris) #插入iris数据
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
> RC.write.table(conn, "iris", iris) #iris是一个data.frame
attr(,"class")
[1] "CassandraConnection"
#查看第1行,Sepal.Length列和Species的值
> RC.get(conn, "iris", "1", c("Sepal.Length", "Species"))
key value ts
1 Sepal.Length 5.1 1.372881e+15
2 Species setosa 1.372881e+15
#注:ts是时间戳
> RC.get.range(conn, "iris", "1") #查看第1行
key value ts
1 Petal.Length 1.4 1.372881e+15
2 Petal.Width 0.2 1.372881e+15
3 Sepal.Length 5.1 1.372881e+15
4 Sepal.Width 3.5 1.372881e+15
5 Species setosa 1.372881e+15
> r <- RC.get.range.slices(conn, "iris") #查看数据集
class(r)
[1] "list"
> r[[1]]
key value ts
1 Petal.Length 1.7 1.372881e+15
2 Petal.Width 0.4 1.372881e+15
3 Sepal.Length 5.4 1.372881e+15
4 Sepal.Width 3.9 1.372881e+15
5 Species setosa 1.372881e+15
> rk <- RC.get.range.slices(conn, "iris", limit=0)
> y <- RC.read.table(conn, "iris")
> y <- y[order(as.integer(row.names(y))),]
> head(y)
Petal.Length Petal.Width Sepal.Length Sepal.Width Species
1 1.4 0.2 5.1 3.5 setosa
2 1.4 0.2 4.9 3.0 setosa
3 1.3 0.2 4.7 3.2 setosa
4 1.5 0.2 4.6 3.1 setosa
5 1.4 0.2 5.0 3.6 setosa
6
不支持的常用操作
- 创建keyspaces,除keyspaces
- 创建列族,删除列族
- 删除一行
- 删除一行的某列数据
6.4.4 RCassandra使用案例
下面通过一个业务需求的例子加深我们对RCassandra的认识。这是一个非常简单的业务场景,业务需求:(1) 创建一个Users列族,包含name,password两列;(2) 在已经存在数据的情况下,动态增加一个新列age。首先在Cassandra命令行,创建列族Users。
[default@DEMO] create column family Users
... with key_validation_class = 'UTF8Type'
... and comparator = 'UTF8Type'
... and default_validation_class = 'UTF8Type';
89a2fb75-f7d0-399e-b017-30a974b19f4a
然后在RCassandra插入数据,包含name和password两列。
> df<-data.frame(name=c('a1','a2'),password=c('a1','a2')) > print(df)
name password
1 a1 a1
2 a2 a2
> RC.write.table(conn, "Users", df) #插入数据
attr(,"class")
[1] "CassandraConnection"
> RC.read.table(conn,"Users") #查看数据
name password
2 a2 a2
1 a1 a1
#新插入: 一行KEY=1234,并增加age列
> RC.insert(conn,'Users','1234', 'name', 'scott')
> RC.insert(conn,'Users','1234', 'password', 'tiger')
> RC.insert(conn,'Users','1234', 'age', '20')
> RC.read.table(conn,"Users") #查看数据
age name password
1234 20 scott tiger
2 NA a2 a2
1 NA a1 a1
#修改: KEY=1的行中,name=a11, age=12
> RC.insert(conn,'Users','1', 'name', 'a11')
> RC.insert(conn,'Users','1', 'age', '12')
> RC.read.table(conn,"Users") #查看数据
age name password
1234 20 scott tiger
2 NA a2 a2
1 12 a11 a1
6.4.5 Cassandra的没落
随着Hadoop的兴起,Hadoop家族产品HBase的广泛使用。有越来越多的基于Cassandra构建的应用,开始向HBase迁移。Cassandra的没落,在技术上可能存在的一些原因。
1. 读的性能太慢
无中心的设计,造成读数据时通过逆熵做计算,性能损耗很大,甚至会严重影响服务器运作。
2. 数据同步太慢(最终一致性延迟可能非常大)
由于无中心设计,要靠各节点传递信息。相互发通知告知状态,如果副本集有多份,其中又出现节点有宕机的情况,那么做到数据的一致性,延迟可能非常大,效率也很低的。
3. 用插入和更新代替查询,缺乏灵活性,所有查询都要求提前定义好。
与大多数数据库为读优化不同,Cassandra的写性能理论上是高于读性能的,因此非常适合流式的数据存储,尤其是写负载高于读负载的。与HBase比起来,它的随机访问性能要高很多,但不是很擅长区间扫描,因此可以作为HBase的即时查询缓存,由HBase进行批量的大数据处理,由Cassandra提供随机查询的接口
4. 不支持直接接入hadoop,不能实现MapReduce。
现在大数据的代名词就是Hadoop,做为海量数据的框架不支持Hadoop及MapReduce,就将被取代。除非Cassandra能够给出其他的定位,或者海量数据解决方案。DataStax公司,正在用Cassandra重够HDFS的文件系统,不知道是否可以成功。让我期待Cassandra未来的发展吧!