2009年4月16日 星期四

Cassandra安装、部署和简单评测

懒得一张张插入图片了。。。可以在这里看有图片的。
http://docs.google.com/Doc?id=ddxvh3dd_6gdnrs8f8&hl=zh_CN


Cassandra简单评测(2009/4/16)
1. 安装
a) 环境
i. Windows Vista Sp1(其实最好是在linux下面安装,不过本本只有Vista和OS X)
ii. Java JDK 1.7 b50(http://www.java.net/download/jdk7/binaries/jdk-7-ea-bin-b50-windows-i586-05_mar_2009.exe,请一定要安装这个版本,因为程序就是基于这个jdk进行开发的,而这个jdk和之前的有很大的差别,不用这个jdk会发生很多类找不到的问题。不过貌似听作者说会将这个限制去掉,到时候其他jdk也可以了)
iii. Eclipse 3.3(这个随便哪个版本了)
iv. Firefox 3.3(这个就是为了看一下cassandra提供的http接口的)
b) 配置
i. 首先从svn(http://svn.apache.org/repos/asf/incubator/cassandra/trunk)上面把cassandra给checkout出来,放在cassandra目录中。我checkout的版本是3月27号的最后那个版本,具体revision忘记了。
ii. 在eclipse新建一个project,选择“java project from existing ant buildfile)
iii. 在ant buildfile 里面选择cassandra中的build.xml,工程名填入cassandra20090327,然后导入。
iv. 因为eclipse设置的workspace是E:\Program\Java2,所以在E:\Program\Java2\cassandra20090327新建一个文件夹叫做“null”,然后将cassandra目录中conf下面的两个文件:storage-conf.xml和log4j.properties复制到cassandra20090327/null下面,打开storage-conf.xml,接下来说明一下相关的配置:
1. 填入主机名称,我有两台机器,所以写成(当然可以写ip地址):
a) lizhenyu-PC
b) lizhenyu-IBM
2. 里面写你需要新建或者读取的table的名称和columnfamily以及conlumntype,可以使用默认的。
3. 就是通过firefox访问时用的端口,可以使用默认的。
v. 配置完以后,我们在eclipse中运行service包中的CassandraServer.java文件,如果出现:

DEBUG - Submitting a major compaction task ...
DEBUG - Started compaction ...RecycleColumnFamily
DEBUG - Submitting a major compaction task ...
DEBUG - Finished compaction ...RecycleColumnFamily
DEBUG - Started compaction ...Super1
DEBUG - Finished compaction ...Super1
DEBUG - Done reading the block indexes, Index has been created
DEBUG - INDEX LOAD TIME: 13 ms.
DEBUG - Submitting a major compaction task ...
DEBUG - Started compaction ...Standard2
DEBUG - Finished compaction ...Standard2
DEBUG - Submitting a major compaction task ...
DEBUG - Started compaction ...Super2
DEBUG - Submitting a major compaction task ...
DEBUG - Finished compaction ...Super2
DEBUG - Submitting a major compaction task ...
DEBUG - Started compaction ...Standard1
DEBUG - Submitting a major compaction task ...
DEBUG - Finished compaction ...Standard1
DEBUG - Submitting a major compaction task ...
DEBUG - Started compaction ...LocationInfo
DEBUG - Submitting a major compaction task ...
DEBUG - Finished compaction ...LocationInfo
DEBUG - Started compaction ...StandardByTime1
DEBUG - Finished compaction ...StandardByTime1
DEBUG - Submitting a major compaction task ...
DEBUG - Started compaction ...TableMetadata
DEBUG - Finished compaction ...TableMetadata
DEBUG - Started compaction ...StandardByTime2
DEBUG - Finished compaction ...StandardByTime2
DEBUG - Started compaction ...HintsColumnFamily
DEBUG - Finished compaction ...HintsColumnFamily
DEBUG - Starting to listen on lizhenyu-IBM:7001
INFO - Running on stage GMFD
说明已经成功运行了,在两台机器上一次如此配置,我的笔记本名字是lizhenyu-IBM,台式机名称是lizhenyu-PC。如果两台机器都配置成功了,你会在eclipse的控制台上看到他们之间的交互信息。
2. 测试
a) 首先在lizhenyu-PC和lizhenyu-IBM上分别启动CassandraService.java
i. 在firefox中输入http://lizhenyu-ibm:7002/或者http://lizhenyu-pc:7002/都能够看到关于这个小小的cluster的信息
ii.
iii.
iv.
v. 我输入的是http://lizhenyu-ibm:7002/,所以写的sql语句也是影响ibm这台机器
vi. 点击SQL,进入数据插入和查询界面
vii. 输入如下图的信息
viii. 点击send,出现The insert was successful : columnfamily=Standard1 key=1 data=xyz
ix. 在查询框中输入
x. 点击send,得到的结果是
xi. 现在说明对于table的操作是没有问题的
b) 在org.apache.cassandra.test中有很多用来测试Cassandra的代码,我测试其中的SSTableTest.java(其他的可以按照这个例子自己尝试,但是StressTest.java里面还是有点问题,我还在和作者交流)。
i. 对于StressTest.java,默认是执行这段代码:
1. BloomFilter bf = new BloomFilter(1024*1024, 15);
2. for ( int i = 0; i < 1024*1024; ++i )
3. {
4. bf.fill(Integer.toString(i));
5. }
6.
7. DataOutputBuffer bufOut = new DataOutputBuffer();
8. BloomFilter.serializer().serialize(bf, bufOut);
9. FileOutputStream fos = new FileOutputStream("C:\\Engagements\\bf.dat", true);
10. fos.write(bufOut.getData(), 0, bufOut.getLength());
11. fos.close();
12.
13. FileInputStream fis = new FileInputStream("C:\\Engagements\\bf.dat");
14. byte[] bytes = new byte[fis.available()];
15. fis.read(bytes);
16. DataInputBuffer bufIn = new DataInputBuffer();
17. bufIn.reset(bytes, bytes.length );
18. BloomFilter bf2 = BloomFilter.serializer().deserialize(bufIn);
19.
20. int count = 0;
21. for ( int i = 0; i < 1024*1024; ++i )
22. {
23. if ( bf.isPresent(Integer.toString(i)) )
24. ++count;
25. }
26. System.out.println(count);
其实就是简单的对数据的序列化和反序列化,将序列化后的东西存储在硬盘上,当要读取数据的时候,对文件进行反序列化,就可以正常显示了。sstable的存储和获取就是一个序列化和反序列化的过程。
正确的结果是:1048576,如果和结果不一样,检查一下吧。
ii. 将这段代码注释掉,去掉LogUtil.init(),readSSTable()和rawSSTableWrite()的注释,变成:
1. LogUtil.init();
2. //DatabaseDescriptor.init();
3. //hashSSTableWrite();
4. rawSSTableWrite();
5. readSSTable();
将rawSSTableWrite()函数的代码改成:
private static void rawSSTableWrite() throws Throwable
{
SSTable ssTable = new SSTable("C:\\Engagements\\Cassandra", "Table-Test-2");
DataOutputBuffer bufOut = new DataOutputBuffer();
BloomFilter bf = new BloomFilter(1000, 8);
byte[] bytes = new byte[64*1024];
Random random = new Random();
for ( int i = 100; i < 1000; ++i )
{
String key = Integer.toString(i);
ColumnFamily cf = new ColumnFamily("Standard1", "Standard");
bufOut.reset();
// random.nextBytes(bytes);
cf.addColumn("C", "Avinash Lakshman is a good man".getBytes(), i);
ColumnFamily.serializerWithIndexes().serialize(cf, bufOut);
ssTable.append(key, bufOut);
bf.fill(key);
}
ssTable.close(bf);
}

结果会出现
KEY:100
Standard1
C
KEY:101
Standard1
C
KEY:102
Standard1
C
……
……
……

因为这个版本的代码有点问题,不知道为什么作者认为101比102小,那么101的md5值也会比102的md5值小,奇怪的论调,貌似没有这样的关系吧。如果你出现类似于这样的exception:key is not written by ascending.那么可以更改org.apache.cassandra.dht包中的decorateKey(String key)函数:
原来的代码:public String decorateKey(String key)
{
return hash(key).toString() + ":" + key;
}
改后的代码:public String decorateKey(String key)
{
//return hash(key).toString() + ":" + key;
return key + ":" + hash(key);
}
c) 其他几个测试文件可以自己回去尝试去运行一下,这里就懒得写了,其实就是分别测试了memtable,对Cassandra的简单压力测试,数据的导入导出等等。
3. 如何使用Cassandra或者说它的接口
a) 其实Cassandra的接口很简单,都放在了org.apache.cassandra.service中的Cassandra.java文件中,主要有以下几个接口:
get_slice,get_slice_by_names,get_column,get_column_count,insert,batch_insert,batch_insert_blocking,remove,get_columns_since,get_slice_super,get_slice_super_by_names,get_superColumn,batch_insert_superColumn,batch_insert_superColumn_blocking,touch,getStringProperty,getStringListProperty,describeTable,executeQuery, 关于怎么使用这些接口,可以看test包中的几个例子,都有介绍,而且看名称应该就能懂都是干嘛的了吧。
过两天我会写一个完整的程序,是关于使用这些interface,不过要做毕业设计,太忙了点这段时间^)^
4. 性能测试
a) 因为这些版本都是development版,所以有很多的println语句,导致我用一台机器让另一台机器插入10w条数据都用了100多秒,现在对于Cassandra的benchmark网上还找不到,Avinash Lakshman说他们facebook内部有对Cassandra和Mysql的benchmark,不过他说不知道能不能发出来,估计要问他的boss,等他的消息了。
5. 疑问
a) SStable的格式,因为源代码的注释中一下说index是放在所有的blocks之后的,在后面又说每隔128字节(一个block)就有一个index,晕死,回头再看看源代码
b) 消息序列化中还有点问题,Jonathan Ellis说源代码没有问题,但是我的程序一直都无法通过。
c) 对于Cassandra的failure detection机制我还没有看懂,Neophytos Demetriou建议我去看这篇论文The φ accrual failure detector (http://ddg.jaist.ac.jp/pub/HDY+04.pdf),感兴趣的可以看看,对读懂源代码为什么这样写有帮助。
6. 后续工作
a) 在Cassandra中设计一个庆祥上次给我的任务,看看效果怎么样(不过现在还不能看出性能是不是能比mysql优秀)。
b) 继续深入源代码,因为如果要使用Cassandra的话那么很多的参数变更都能影响整个服务器的性能的,例如对于SSTable中block大小的设定,默认是128bytes,而且没有对外提供更改的接口,如果想要部署Cassandra,还有很多工作要做,需要整理出自己的接口,需要对自己的用户量,业务进行分析,看看什么适合Cassandra
c) Thrift:因为我都是用java对Cassandra进行操作,所以直接跳过了thrift这一步,接下来需要了解一下thrift的详细内容,以后用其他语言操作Cassandra就方便了。
7. 对于是否能部署,我现在还不能下结论,一方面没有拿到facebook的benchmark,另外一方面facebook肯定还有其他的措施没有发出来的,我想Cassandra本身肯定是没有问题的,关键是了解他们内部工作机制,怎么去使用它,更改它使得它适合我们的条件,怎么去开发一些和Cassandra配合使用的东西,我想这才是我们需要关心的

沒有留言:

張貼留言