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未来的发展吧!

results matching ""

    No results matching ""