Hycz's Blog

Life is a game. Why so serious?

Category Archives: Daily Work

Cassandra 0.8.0源码包简介

一、overall

这个是Cassandra 0.8.0在Eclipse中配置完毕之后的有关于源码的部分,截图如下:



在正确配置之后,这个工程中应该有7个文件夹,分别是(1)java源代码(src/java);(2)生成java源代码(src/gen-java);(3)thrift生成java源代码(interface/thrift/gen-java);(4)cql的jdbc源代码(drivers/java/src);(5)cql的jdbc测试代码(drivers/java/gen-java);(6)单元测试代码(test/unit);(7)长时间测试代码(test/long)。

虽然文件夹是这么多,其实可以对所有的代码分个类,第一类是纯源代码,第二类是生成代码,第三类是测试代码。如果按照产品进行分类的话,那么也可以分为:第一类是Cassandra服务器端,第二类是Cassandra的Cli,第三类是CQL的JDBC,不过这里依赖关系比较多,所以也不尽然。

二、生成代码(gen-java)

那么先从不太重要的讲起,生成代码。所谓生成代码,就是在src版本中不存在,而是在build的时候生成的代码,在src版本中只有关于这些内容的中间语言版本。我的理解是,这是为了跨语言,比如我现在用的是java,那么就把那中间语言翻译成java,然后生成相应的java文件进行使用。

在上述的代码中,src/gen-java和interface/thrift/gen-java中的代码都是生成代码。Cassandra现在看来真是一个庞然大物,糅合了各种技术在其中,这里的生成代码的技术就用到了3种。

  • Antlr
    这个东西主要是生成自己的语法解析器,简单来说,用之前的JLine进行命令行的IO,然后把获得的命令在这里与相应的函数进行关联。使用的包是lib文件夹下的antlr-3.2.jar。具体用法见这里:http://wenku.baidu.com/view/d8580e5f804d2b160b4ec074.html。在源代码中,下面2个包使用Antlr生成的:src/gen-java下的org.apache.cassandra.cliorg.apache.cassandra.cql,原始文件是src/java/org/apache/cassandra/cli/Cli.gsrc/java/org/apache/cassandra/cql/Cql.g。具体的生成顺序(根据build.xml中),首先是检查生成语法(check-gen-xxx-grammar),从一个*.g 文件生成一个*.token文件,比如,在CLI中,就是从Cli.g文件生成了Cli.token文件,然后生成语法解析器,用生成xxxLexer.java和xxxParser.java,比如,在CLI中,生成了CliLexer.java和CliParser.java。
  • Avro
  • Thrift
    Avro和Thrift放在一起讲,下面的话引自这里:http://www.webguo.com/2011/02/11/avro_vs_thrift.html。“Avro和Thrift都是跨语言,基于二进制的高性能的通讯中间件. 它们都提供了数据序列化的功能和RPC服务. 总体功能上类似,但是哲学不一样. Thrift出自Facebook用于后台各个服务间的通讯,Thrift的设计强调统一的编程接口的多语言通讯框架. Avro出自Hadoop之父Doug Cutting, 在Thrift已经相当流行的情况下Avro的推出,其目标不仅是提供一套类似Thrift的通讯中间件更是要建立一个新的,标准性的云计算的数据交换和存储的Protocol。 这个和Thrift的理念不同,Thrift认为没有一个完美的方案可以解决所有问题,因此尽量保持一个Neutral框架,插入不同的实现并互相交互。而Avro偏向实用,排斥多种方案带来的 可能的混乱,主张建立一个统一的标准,并不介意采用特定的优化。Avro的创新之处在于融合了显式,declarative的Schema和高效二进制的数据表达,强调数据的自我描述,克服了以往单纯XML或二进制系统的缺陷。Avro对Schema动态加载功能,是Thrift编程接口所不具备的,符合了Hadoop上的Hive/Pig及NOSQL 等既属于ad hoc,又追求性能的应用需求.”在源代码中,使用Avro生成的是以下3个包:src/gen-java中的org.apache.cassandraorg.apache.cassandra.db.migration.avro以及org.apache.cassandra.utils.avro,他们都是从文件src/avro/internode.genavro中生成的。在源代码中,使用Thrift生成的是interface/thrift/gen-java中的org.apache.cassandra.thrift包,原始文件是interface/cassandra.thrift文件。

三、测试代码(test/unit, test/long and drivers/java/test)

没什么好讲的,就是针对每个包中的代码的测试。

四、源代码(src/java and drivers/java/src)

src/java中有34个包,有内容的有33个。正如同Cassandra的论文中的行文结构一样,Cassandra其实没有什么层次性,甚至连系统架构图都没有,然后再看各个包的话,可以发现其实是针对一个分布式系统的不同方面的实现,比如在论文中的系统架构章节提到的几个部分:Partitioning,Replication,Membership,Bootstrapping,Scaling the Cluster,Local Persistence,还有一些其他的实现技术,比如SEDA等等。这几个部分算是系统的几个主要模块,但是包与包之间又不是简单的模块关系,反而更像是根据分布式系统各部分相关论文的技术而做的实现,然后再以一种粗暴的方法拼接在一起,不牢固的地方再加上其他的实现加以过度。当然,这是我粗看之下的愚见,不能作数,但是Cassandra其实算不上优雅,更像是一个缝合憎恶。

所以,将这些包分成几个大的部分比较好:

  • 存储和数据模型
    这个部分如同名字,其实应该分为2个部分,但是由于这两部分的实现过于紧密(比如SStable和Memtable的实现就在不同的包中),只好归为一类。作为最底层的部分,存储部分的主要参照是Bigtable中的SStable+Memtable模型,使用这个模型就不可避免地需要用到BloomFilter和Compaction,当然还有一些cache的技术也算在这个部分,数据模型部分的主要参照也是Bigtable中的Keyspace+Row+ColumnFamily+Column的模型,不过Cassandra又在其中加上了SuperColumn一层,除了模型的实现,还有模型提供的各种操作的实现也在其中,此外,还要加上CommitLog的相关实现。具体的细节不在这里讨论,相关的包是以下几个:
    org.apache.cassandra.io
    org.apache.cassandra.io.sstable
    org.apache.cassandra.io.util
    org.apache.cassandra.db
    org.apache.cassandra.db.columniterator
    org.apache.cassandra.db.commitlog
    org.apache.cassandra.db.context
    org.apache.cassandra.db.filter
    org.apache.cassandra.db.marshal
    org.apache.cassandra.db.migration 
    org.apache.cassandra.cache 
  • P2P
    这个部分是用来实现P2P,也就是去中心化架构的,主要是实现了一个分布式哈希表(DHT),其中实现了几种不同的Partition方案供选择。相关的包是这个:
    org.apache.cassandra.dht 
  • 副本
    这个部分是用来实现分布式系统中常用的副本机制的,这里也提供了几种副本策略。关于副本的设置问题,在配置文件中有副本策略的设置,此外,还有副本数量的设置是写在每个Keyspace的Metadata中的。相关的包是这个:
    org.apache.cassandra.locator 
  • Gossip
    这个部分实现了Gossip,用来进行分布式系统中的成员管理。相关的类是下面这个:
    org.apache.cassandra.gms 
  • SEDA
    这个部分实现了SEDA的框架,用于更高效的并行操作。相关的类是下面这个:
    org.apache.cassandra.concurrent 
  • 通信
    这个部分实现了分布式系统内部用于通信的消息机制,以及内部传输的数据流机制。相关的包是以下几个:
    org.apache.cassandra.net
    org.apache.cassandra.net.io
    org.apache.cassandra.net.sink 
    org.apache.cassandra.streaming 
  • 请求调度
    对到达的请求进行简单的调度,相关包是:
    org.apache.cassandra.scheduler 
  • 服务封装
    这个部分实现了系统对外的调用接口,无论系统内部是如何实现的,对使用者来说,只需要从这里的服务中进行调用就可以了。此外,与hadoop的接口算在其中。相关的包是下面这2个:
    org.apache.cassandra.service 
    org.apache.cassandra.thrift 
    org.apache.cassandra.hadoop 
  • 客户端
    这个部分包括了用于管理系统的命令行接口和CQL客户端,至于Thrift客户端,那个在生成代码中。相关的包是下面这几个:
    org.apache.cassandra.cli
    org.apache.cassandra.client
    org.apache.cassandra.cql 
    org.apache.cassandra.tools 
  • 配置
    这个部分用来读取配置然后导入到系统中。相关的包是下面这个:
    org.apache.cassandra.config 
  • 授权与安全
    这个部分实现的是简单的用户授权管理和安全管理。相关的包是下面几个:
    org.apache.cassandra.auth
    org.apache.cassandra.security
    org.apache.cassandra.security.streaming  
  • 憎恶的缝合线
    好吧,这里卖萌了,其实这里就是我所说的用来对整个系统进行修修补补的地方,比如为了实现某个功能,但是少了个什么东西,于是就实现了放在这里,具体是下面2个包:
    org.apache.cassandra.utils
    org.apache.cassandra.utils.obs 
Advertisements

2011/07/19 “iff”, “if” and “only if”

iff 等同于 if and only if

p if q 等同于 p <= q

p only if q 等同于 p => q

p iff q 等同于 p <=>q

2011/07/11 通过JMX与Cassandra交互

1、首先去http://mx4j.sourceforge.net上下载3.0.1版本以上的MX4J库

2、解压后在lib文件夹下找到mx4j.jar和mx4j-tools.jar,拷贝到cassandra/lib下,重启cassandra

3、在jdk的bin目录中找到jconsole,启动,下面

3.1、如果是jconsole和cassandra都在一台机器上,那么在Local Process块中选择 org.apache.cassandra.thrift.CassandraDaemon

3.2、如果不在一台机器上,那么在Remote Process块中输入需要连接的<hostname>:<port>

——————————————–渣翻译来了————————————————————-

JMX:

JMX是一个Java API,通过两种方式提供了application的管理。一,JMX让你了解你的application的健康状况,和总体性能表现(例如memory,threads,和CPU usage),这些都是普遍适用于所有Java application的。二,JMX让你能够接触到你的application中(已经仪表化的application)的特定的方面。

所谓仪表化,就是指将application code包起来,以提供从application到JVM的hook,这使得JVM能够收集一些额外工具能够使用的数据。这些工具包括监视代理(monitoring agents),数据分析工具(data analysis tools),分析器(profilers)等。JMX不光能让你看到这些数据,还能在运行时更改application的值,以管理这些application(如果启动了这项功能)。

JMX所作的控制操作包括以下:

  • 低可用内存的检测,包括堆中每个刻度空间(graduation space)的大小
  • 进程信息,例如死锁检测,进程数量的峰值,以及当前活动进程数量。
  • 详细的类加载器 追踪
  • 日志级别控制
  • 应用的基本信息,例如application的运行时间,classpath等等

jconsole就是一个JMX代理,当然也有其他的JMX代理。

MBeans:

MBean,就是 managed bean,这是一个特殊的java bean类型,代表着JVM中一个可被管理的资源。MBeans与一个MBean server交互,以让他们的功能远程可用。

2011/06/29 难道论文这样写?

今天李葆春教授来实验室交流,他的presentation题目是<<Seen As Stable Marriages>>,介绍了一个关于stable matching的新用法,将stable matching的方法和optimization的方法做了比较。话说我觉得他的鸟文肯定讲的比中文好。

重点不在于他的主题,而是他的presentation的组织方法。虽然是介绍一个方法,但是他从一个男女配对的故事入手,引出了主题,然后用两个用例,VM迁移,和content ISP与eyeball ISP,介绍了他的方法的用法。这个presentation来自于一篇已经发表的paper,不过不是full paper,两个用例只留下了一个,但无论如何,他的方法有个故事。这让我想到了另一篇paper,Lamport写的<<The Part-Time Parliament>>,也就是那篇Paxos算法的原始论文,那篇论文也是用了一个故事作为引子。同学研究算法,老师也是让他为自己的算法想出一个故事。《算法导论》中的算法也都是有相应的故事作为依托,比如动态规划,贪心算法等

看来研究算法或方法时,还是需要一个好的故事,让算法生动起来,并且让别人看到算法或方法的使用价值。

2011/06/28 BigTable中与Cassandra中的数据模型比较

一、Cassandra中的典型数据结构

二、BigTable中与Cassandra中的数据模型比较

BigTable中的数据模型更加像是建立在关系型数据库的表之上的,一个KeySpace就类似于从前的一个Table。所不同的是,BigTable中加入了几个新的特点:

1,按列存储,对于稀疏表更加友好;

2,Column Family,翻译过来就是列族,其实呢,就是把几个关联性强的列储存在一起,这个概念既是逻辑上的,也是物理上的,但是使用者其实并不需要太过关心于Column Family,设计时也不会从Column Family开始

3,历史数据,这里像是借鉴了数据库概念中的时态数据库(Temporal Database),保留了一个column中的历史数据,于是引入了timestamp。

所以呢,BigTable的数据模型更像是这样:

其中的值部分可能是稀疏的,但是按列存储避免了稀疏大表的资源浪费。

Cassandra中的数据模型更加像是建立在BigTable之上,然后加入了一个SuperColumn的概念。然后无论是网上流传的Cassandra中的数据模型使用方法,还是《Cassandra The Definitive Guide》中所介绍的数据模型部分,似乎都与BigTable中的数据模型迥异了,原本的BigTable还有与传统的Table的类比之处,如KeySpace与Table,Column与Column,但是在Cassandra中,KeySpace类似于Application,ColumnFamily类似于Table。个人觉得原因有两个:

1,由于引入了SuperColumn的概念,使得数据模型从BigTable中的KeySpace->Key->ColumnFamily->Column,变成了KeySpace->Key->ColumnFamily->Column或者KeySpace->Key->ColumnFamily->SuperColumn->SubColumn,于是数据维数上升了,而且变得不确定了,有时4维有时5维的数据模型就缺少一个通用的使用方法。虽然SuperColumn的引入丰富了整个数据模型,但是我认为由于原本的四维数据模型已经足够简约和使用,SuperColumn只能算作锦上添花,而且由于Cassandra本身功能不够强大,如果使用SuperColumn回来带来一些问题,例如索引问题,条件搜索的实现更加困难。

2,Cassandra的固有实现问题。可能在一开始的时候,Cassandra的开发人员对BigTable的模型理解就有偏差(这里并没有对不对的问题,只是与更广泛的理解略有不同),所以KeySpace的实现就不是当做一个Table来实现的,所以才会出现早期版本中必须重启整个Cassandra集群才能添加新KeySapce的情况,在后来的版本中,多KeySpace也并不被鼓励。

所以,Cassandra的数据模型更像是这样:

如图中所示,虽然这是一个KeySpace,但是这个KeySpace实际上是被切成了几份,Key虽然看似是同等的地位,但是实际上是分别专用于不同的ColumnFamily,并不能通用,他们的命名方式也各不相同。总的来说,这也是一个稀疏的大表,只不过空洞部分更加集中(图中XX部分),而有意义的ColumnFamily中(着色部分)空洞则少得多。而由于按列存储的机制,确实使得ColumnFamily看起来更像一个Table了。

比较BigTable和Cassandra中的数据模型,二者其实很相似,如果真的愿意的话,实际上可以互相转化。不过针对BigTable的设计更偏重于以row为单位,一个row中的内容可以非常丰富,而针对Cassandra的设计更偏重于以ColumnFamily为单位,KeySpace的意义被淡化了。

2011/06/23 2PC和现实业务处理

看了一篇2004年的博文(地址:http://www.eaipatterns.com/ramblings/18_starbucks.html),作者从架构师的角度分析了starbucks的业务流程,然后将其与2PC做了下比较,虽然是04年的文章,但是还是很有启发性。

现实中的业务流程往往是同步加异步的模式,同步的部分是收银员,那里有一定的程序必须得按顺序完成,当订单下了之后,便进入异步的业务处理,这样既可以灵活的调整各个部分的服务能力,也不会浪费资源。2PC虽然过程很简单,但是由于在业务完成前,无论是服务者还是客户都不能离开,这降低了整体的效率,浪费了很多资源。

一个简单的例子是我亲身经历的,那就是麦当劳和肯德基,在麦当劳中,使用的是同步加异步的策略,收银员接受订单,然后把订单放到一边,然后就接受下个人的订单,另有员工按照订单把食物手机好给客户,于是各司其职,收银员不够那就加收银员,后面的订单处理不够那就加订单处理人员,虽然会出现由于食物没做出来而使后下订单的人先拿到食物,但是这只是很小的问题。相对的,肯德基的策略更像2PC,策略很简单,一个员工既要收钱,也要去收集食物,排队的客户必须等前面的人拿到食物才能轮到自己,虽然正在服务的客户感觉很好,但是对服务者来说,花费了大量的时间在不用业务的转换上,各个业务的专业性也不够,对客户来说,本可以下完订单就去干自己的事,比如洗个手,坐着等,但是实际上却需要站着等待所有队伍前面的人的服务时间。

另一个例子是google的架构,那篇文章的作者就是google的架构师,因而那篇文章的思想与google的策略十分相似。众所周知,google的架构是主从模式,为了防止主节点成为瓶颈,google做了大量的优化,实际上,主节点处理的就是同步的部分,每个业务的开始都需要与主节点通信,然后真正处理的,是从节点,这部分的处理就是异步的部分,这里的处理跟业务到来的顺序没有必然关系,而是跟各个业务的特点和实际内容有关。

所以,2pc可能看起来很美,而且简单,但是真的使用的话,可能需要高超的技巧,不然很容易成为一场灾难。同步加异步的方法恐怕是更为有效的方案

2011/06/20 在Eclipse中配置Cassandra——配置文件介绍2

接上回

https://hycz.wordpress.com/2011/06/17/cassandra-yaml/

8.

今天介绍一下conf文件夹下的其他配置文件

首先是log4j-server.proprties,这个和cassandra.yaml一样是必须的配置文件。具体的用法参见http://kdboy.iteye.com/blog/208851

下面是passwd.properties,这是一个SimpleAuthenticator的用户密码配置,每行格式是username=password,如果-Dpasswd.mode=MD5,那么密码部分是md5 digest,否则,密码部分是明文。(用户名中空格用’\ ‘)

接下来是access.properties,这是一个SimpleAuthority的访问配置,每行格式是KEYSPACE[.COLUMNFAMILY].PERMISSION=USERS,其中,KEYSPACE是keyspace名,COLUMNFAMILY是column family名,PERMISSION是<ro>或者<rw>,意思是read only或read-write,USERS是一系列用户名,用逗号隔开,这些用户名必须在passwd.properties中定义。例:Keyspace1.Standard1.<rw>=jsmith,Elvis Presley,dilbert

最后是cassandra-topology.properties,这是一个定义cassandra集群拓扑的配置,每行格式是Cassandra Node IP=Data Center:Rack,其中,等号左边是ip,右边是数据中心名和机架名(似乎只是个名字,不用定义),这里主要是用来判断节点的临近性,由org.apache.cassandra.locator.PropertyFileSnitch使用。注意,如果ip不明的话,比如后来加入的节点,那么ip部分就用default代替。如果需要使用ipv6,那么需要在cassandra-env.sh中把其中一个参数设置改为:JVM_OPTS=”$JVM_OPTS -Djava.net.preferIPv4Stack=true”。

2011/06/15-17 在Eclipse中配置Cassandra——配置文件介绍

接上回https://hycz.wordpress.com/2011/06/14/20110614-%E5%9C%A8eclipse%E4%B8%AD%E9%85%8D%E7%BD%AEcassandra2/

7.
今天要对Cassandra进行配置,这话有点拗口,简单来说,就是改一下conf文件夹里的配置文件,因为原来的是默认设置,而且是针对linux的文件系统的,这里要改成windows下的。首先是cassandra.yaml文件(这坑好大。。。慢慢填),主要翻译翻译注释。。。。

1、cluster_name:集群名,主要用来防止机器加入到其他的逻辑集群中
2、initial_token:cassandra中有个token环,每个节点都负责其中的一部分,这个参数就是用来设定这台机器负责哪部分的。如果空着不写,那么就自动取负载最重的节点所拥有的token范围的一半。如果取不到负载信息,那么就随机取一段。
3、auto_bootstrap:cassandra中的节点其实还是分了2种,一个是seed节点,一个是non-seed节点,一个节点要加入集群实际上还是要一个入口,这个入口就是种子节点,所以一次能够加入集群的节点数量是有限的,即种子节点的数量,如果需要加入集群的节点数量多于这个阀值,那么就需要分阶段进行加入操作。这个参数是用来设定一个非种子节点是否在启动时自动从已有节点中迁移数据进来。默认false
4、hinted_handoff_enable:这个参数涉及了cassandra的一个机制,当一个写操作所针对的副本节点down掉的时候,cassandra会在另一台活着的副本几点上写一个hint(提示?暗示?还不如说是个便签。。。),这个hint用来表明那台down掉的节点需要重新执行这个写操作。如果所有的副本节点都死了,而且一致性等级是ConsistencyLevel.ANY(五种?ZERO,ONE,QUORUM,ALL,ANY,这里ANY是说只要一个写操作在任何地方成功了,hint写也算。。。那就算成功。。),协调节点(coordinating node)会在本地写下这个hint。这个机制主要是用来减少暂时失效节点通过活着的节点重新恢复到一致状态 所需要的时间,并且在不需要一致性的情况下提供额外的可用性。
     max_hint_window_in_ms:节点死掉之后保留hint的最长时间,死太久了,超过这个时间那么之前写的hint就被丢弃。
     hinted_handoff_throttle_delay_in_ms:每发送一行或者行碎片时sleep这么长时间?这里不确定
6、authenticator:认证后端,实现接口IAuthenticator,用来识别用户
7、authority:授权后端,实现接口IAuthority,用来限制访问,提供通行权
8、partitioner:这里是Cassandra中很重要的一部分,设置了Cassandra中数据的数据分割方式,用通俗的话来说,就是数据是以怎样的规则分布在整个集群的许多节点中的,数据的分割是以row为单位的,row使用key来唯一辨别的,所以其实就是key的分布。设置的值是个类名,这个类需要实现IPartitioner接口。Cassandra提供了几种分布方式如下

org.apache.cassandra.dht.RandomPartitioner
org.apache.cassandra.dht.ByteOrderedPartitioner
org.apache.cassandra.dht.OrderPreservingPartitioner (deprecated)
org.apache.cassandra.dht.CollatingOrderPreservingPartitioner(deprecated)

第一个是随机分割,使用md5;第二个是根据key的每个byte的字母顺序进行排序,这种排序支持row级别的(其实就是key啊)范围查询,但是对于顺序插入的负载,这种分割会存在热点问题,但是没办法啊。。。不然怎么顺序查询。。。泪奔;第三个是第二个的废弃版本,格式比第二个低效,使用UTF-8编码的字符串当做key;第四个似乎是和第三个差不多的,不过用了另一种排序方式,反正都被废弃了,不管了。
9、data_file_directories:存data的目录
     commitlog_directory:存commitlog的目录
     saved_caches_directory:存cache的目录
     commitlog_rotation_threshold_in_mb:一个阀值,单位MB,当commitlog超过这个大小时,就产生一个新的段
10、commitlog_sync:这里设置commitlog的同步方式,应该就是从内存中同步到磁盘上做持久化,这里有2种设置,一个是batch,一个是periodic。在batch模式中,只有当commit log同步到了磁盘上之后才会执行写操作,在执行同步之前,将会等待CommitLogSyncBatchWindowInMS毫秒,等其他的写操作结束。在periodic模式中,写操作会被立即执行,无视commitlog有没有写到磁盘上,而commitlog则是每隔commitlog_sync_period_in_ms这么长时间才周期性的进行同步。
      commitlog_sync_period_in_ms:commitlog以periodic模式同步时的周期值,单位毫秒。
11、seed_provider:这个参数是seed节点的设置,首先是要设置seed_provider的子参数- class_name,这里需要制定一个类来提供seed功能,这个类需要实现SeedProvider接口,然后设置子参数- seeds,也就是seed节点的地址,多个地址间用逗号隔开
12、flush_largest_memtables_at:这是第一个紧急状况压力阀值,这里的值设置在0-1.0之间,这个值的意思是每当full garbage collection之后,如果堆的使用率高于这个阀值的话,那么就会把最大的memtable flush到磁盘上。设到1.0就是永远不执行,也最好不要低于CMSInitiatingOccupancyFraction。
13、reduce_cache_sizes_at:这是第二个紧急状况压力阀值,在full garbage collecion之后,如果首次出现堆使用率高于这个阀值,那么cassandra就会降低cache的最大容量,并且降低cache的当前大小。
reduce_cache_capacity_to:当上述情况发生时,cache的最大容量降低比例
14、concurrent_reads:并发读的数量,当负载高于内存中能满足的数据时,读会成为cassandra的瓶颈,建议设置成16*驱动器数量
      concurrent_writes:并发写的数量,一般对于写操作,IO不会成为瓶颈,计算机的处理器core数才是影响其性能的关键,所以可以设置成8*core数量
15、memtable_total_space_in_mb:memtable的最大值,省略的话自动设置成堆的三分之一大小
        memtable_flush_writers:memtable flush的进程数量,由于flush进程会被磁盘io所阻塞,而且当被阻塞时,每个进程都会持有一个memtable,所以当堆很大,而且有很多数据目录时再去提高这个值。省略的话默认设置为数据目录的数量
      memtable_flush_queue_size:当memtable满了的时候能够进入等待flush队列的数目,最小应该设置为一个Column Family中辅助索引的最大数目
16、sliced_buffer_size_in_kb:处理连续的column slice的buffer大小
17、storage_port:TCP的端口
18、listen_address:其他节点用来连接的地址,也就是本机的地址,空着的话会自动调用InetAddress.getLocalHost()来填这个空,一般是填本机的hostname,不能填0.0.0.0
19、rpc_address:Thrift RPC service所绑定的地址,客户端会连接这个地址,0.0.0.0意味着监听所有,空着同上。
      rpc_port:Thrift RPC service绑定的端口
      rpc_keepalive:是否保持rpc连接存活,也就是用不用长连接吧
20、rpc_min_threads:对于客户端RPC,Cassandra使用一个进程进行处理,这是很昂贵的消耗,所以更好的方法是使用连接池。不过这里还是提供了rpc数量设置,这个参数是最小进程数。注释掉就默认16
      rpc_max_threads:这个参数是最大进程数,注释掉默认无上限
21、rpc_send_buff_size_in_bytes:rpc连接的socket buffer大小,可以注释掉
      rpc_recv_buff_size_in_bytes:rpc连接的socket buffer大小,可以注释掉
22、thrift_framed_transport_size_in_mb:thrift的框架大小,设成0就不用TFramedTransport,而用TSocket,但是不推荐设成0
23、thrift_max_message_length_in_mb:thrift消息的最大长度,包括所有的字段(field)和thrift内部的开销
24、incremental_backups:如果设为true的话,Cassandra会建立到每个已在本地flush后或stream之后的sstable的硬链接,这些sstable在Keyspace数据的备份或者子目录中。移除这些链接将是操作者的职责。一般设成false?这个参数没看懂。。。
25、snapshot_before_compaction:是否在每次compaction之前做snapshot,注意,如果设为true的话,cassandra是不会去清理这些snapshot的,所以要手动清理,估计会很多,很麻烦。。。一般设成false吧
26、compaciton_thread_priority:设置compaciton进程的优先级,注释掉的话默认设为1,在java中1是最低。。。。
27、column_index_size_in_kb:当一个row的内容超过这里设置的大小时,会添加column索引,默认设成了64,如果column的值都很大,或者有很多column的话,可以相应设置更大的值。这带来了另一个很矛盾的问题,即使只是读一个单独的column,Cassandra也需要反序列化(deserialize)这部分索引数据,所以这些索引数据是越小越好,一个column的情况可能比较极端,但至少能在读一行的一部分时(这种情况比较多见)能小一些;但是每次存取时是都需要先访问索引数据的,所以我们也不能一味图小,而使得索引中无法包括足够有用的信息。说了这么多废话,意思就是这个值要根据应用好好斟酌,不能太大,不能太小。默认64KB
28、in_memory_compaction_limit_in_mb:在内存中进行compaction的row的最大大小,超过这个值的话,超过的部分会暂时放到磁盘上,那么这个compaction效率就不行了。一个消息会log下来,用来辨别这个row key
29、concurrent_compactors:compation进程的数量,注释掉默认设置为处理器的数量,建议是使用多个进程进行处理,这样可以在读写混合型负载中保持读性能,原因是这样避免了在长时间的compaciton中sstable的积聚。。。其实嘛,就是compaciton的快一些。。
30、compaction_throughput_mb_per_sec:设置了一个阀值限制compaction输出的速率,单位是MB/s,要知道,compaciton是一个很差火的操作,同时消耗CPU,MEMORY,IO资源,所以compaction的时机非常重要,否则会对整个系统产生重大影响。compaction的相关设置都值得好好研究,如果希望系统高效的话,这个值的设置还是要结合实际使用情况。插入数据的速度越快,那么compaction的速度也要越快,以控制sstable的数量。一般设置这个值为插入数据速率的16到32倍比较好。设为0的话就没有阀值。
31、compaction_preheat_key_cache:是否在compaction过程中跟踪已缓存的row key,并且重新缓存这些row key在compact之后的sstable中的新位置。如果有足够大的key缓存的话,可以设为false(为什么。。。。)
32、rpc_timeout_in_ms:等待其他节点回复的时间,超过这个时间则执行的命令失败
33、phi_convict_threshold:这里就是论文中提到的Failure Detection所用到的phi,这里有一个算法,算出一个节点的phi值,如果超过阀值,那么就判断这个节点已经down掉。一般用不到,注释掉
34、endpoint_snitch:这里的参数值是一个实现了IEndpointSnitch接口的类,用来让Cassandra知晓网络拓扑,以更高效的route(这里忍不住吐槽一下,翻译成路由真是不知所云,还不如直接翻译成寻路)请求。snitch也是一个不好理解的地方,原意为告密,实际是理解为告知别人自己的拓扑结构么?那这个参数叫端点告知?Cassandra提供了3个策略

org.apache.cassandra.locator.SimpleSnitch:
org.apache.cassandra.locator.RackInferringSnitch:
org.apache.cassandra.locator.PropertyFileSnitch:

第一个是是简单策略,就是一个简单的邻近策略,能够提高缓存的locality(本地性?或者说集中性?),但是不能进行读修复(读修复能够进一步提高吞吐?);第二个是机架策略,邻近性由机架和数据中心决定,这里假设邻近性由不同节点的ip(ipv4)的第三个和第二个8位数(A.B.C.D中的B和C。。。)来决定,也就是说ip相近,那就认为更邻近;第三个是用配置文件显性地写好了哪些节点邻近,配置文件是cassandra-topology.properties。
35、dynamic_snitch:是否使用dynamic_snitch。dynamic_snitch是包裹在endpoint_snitch外,用来监控读延迟,以避免从已经变慢的主机上进行读取。
      dynamic_snitch_update_interval_in_ms:多久进行一次分数计算(代价昂贵?)
      dynamic_snitch_reset_interval_in_ms:多久充值所有机器的分数,通过这样的操作很可能可以让坏掉的节点恢复
      dynamic_snitch_badness_threshold:这里又提到了另一个机制,副本的pin(钉住?不知怎么翻译),意思就是反复从一个副本上读数据,这样cache的能力会得到提高。当这个参数的值(0.0到1.0闭区间)设置为大于0的时候,这个机制就会启动。但是基于dynamic snitch机制,副本是有分数的,dynamic snitch是用来监控读延迟,并且给主机打分,以评出优劣,然后选择更优的副本提供读,当一个已经pinned的副本变坏时,就需要换一个性能更优的副本pin住提供读。那么如何判断一个副本已经很坏了,需要换一个副本提供读呢?这里就用到了这个阀值,举个例子,当这个值为0.2时,当已经被pin的副本的分数比最快的副本的分数低20%时,cassandra就会选择另一个副本。

36、request_scheduler:这个参数是一个实现了RequestScheduler的类,用来基于特定的策略来调度传入的客户端请求,当一个Cassandra集群上有多租户时,这个调度会很有用。这个调度只是针对客户端请求,并不会影响内部节点通信。下面是提供的几个类

org.apache.cassandra.scheduler.NoScheduler
org.apache.cassandra.scheduler.RoundRobinScheduler

第一个是不使用任何调度;第二个是使用round robin调度客户端请求,每一个不同的request_scheduler_id都有一个单独的队列,具体的option会由request_scheduler_options设置
      request_scheduler_options:如果用NoScheduler,那么没有option,如果用RoundRobin,那么会有3个子选项:1,throttle_limit,每个客户端的请求数量阀值,超过这个数量的请求都会进入队列,大小设置一般是(并行读+并行写)*2;2,default_weight,可选选项,默认权值的设置,原先是1,但是可以自己设定;3,weights,也是可选选项,如果不写,那么权值会被设置成default_weight,这个参数是设定每轮RoundRobin中,基于scheduler id的权值,有多少请求会被处理,scheduler id的设置在下面。
      request_scheduler_id:基于这个id来进行请求调度,当前唯一的选择是keyspace
37、index_interval:对一个sstable的row key进行采样的大小,采样越大,index越有效,但是要消耗更多的空间
38、encryption_options:节点间的加密

2011/06/14 在Eclipse中配置Cassandra_2

接上回https://hycz.wordpress.com/2011/06/13/20110613-%E5%9C%A8eclipse%E4%B8%AD%E9%85%8D%E7%BD%AEcassandra/

  1. 见上回
  2. 见上回
  3. 见上回
  4. 遇到问题,开始Debug的时候出现
    “‘Launching CassandraDaemon’ has encountered a problem.
    Cannot connect to VM”Details中:
    “Cannot connect to VMselect failed”不光是这个项目,我新建了一个最简单的project写了个helloworld都不能用debug,说明这是eclipse层的问题。具体出错处是什么socket出错,网上的说法就几种:1,有其他程序占用了Eclipse的Debug端口,导致出错;2,操作系统的socket出了问题要重置。对于第一种解释,虽然我表示同意是另一个程序影响了Eclipse,但是实在难以找到相应的程序,对于第二种解释,我又找不到win7下的重置sock的工具。无奈之下,就用了360的LSP修复,修复之后Debug能用了,但是不能打开网页了。我在修复前看了一下,使用到LSP的非系统程序只有2个,都是我的游戏代理,一个是27代理,一个是迅雷加速器,恐怕问题就出在他们身上。无论如何,网页是打不开了,qq还在,于是重启看看。重启之后,依然不能上网,连qq都上不去了,打开360,居然要求自动修复,那就自动修复吧,结果瑞星狂叫360是木马,现在吧,我觉得瑞星更像木马一些。修复完了,按要求重启,qq能上了,但是网页打不开,这种情况好像DNS坏了一样,就用cmd ping了一下百度,居然ping的通,然后我又用Access Connections诊断了一下网络故障,他叫我检查防火墙设置。360防火墙怎么莫名其妙开了,关掉,不能开网页,瑞星防火墙,关掉,能开网页了。瑞星果然是娱乐货,没事弄个免费,天天弹那些狗屎免费游戏,真的考虑要不用它了。又启动了一下迅雷网游加速器,果然问题再现了,使用他自带的LSP修复,然后问题消失。果然还是LSP引起的问题么。这种诡异的问题不要再碰到了啊!这样一来,代理还是能用,只是用完了要修复,不能一边wow一边debug了。。
  5. 类中的static{}属性,似乎是在调用类的方法时,会首先执行的代码,在Cassandra的org.apache.cassandra.service.AbstractCassandraDaemon类中,就有这么一段,是用来初始化logging的
    //Initialize logging in such a way that it checks for config changes every 10 seconds.
        static
        {
        	String config = System.getProperty("log4j.configuration", "log4j-server.properties");
            URL configLocation = null;
            try
            {
                // try loading from a physical location first.
                configLocation = new URL(config);
            }
            catch (MalformedURLException ex)
            {
                // load from the classpath.
                configLocation = AbstractCassandraDaemon.class.getClassLoader().getResource(config);
                if (configLocation == null)
                    throw new RuntimeException("Couldn't figure out log4j configuration.");
            }
            PropertyConfigurator.configureAndWatch(configLocation.getFile(), 10000);
            org.apache.log4j.Logger.getLogger(AbstractCassandraDaemon.class).info("Logging initialized");
        }

    这里首先定义了一个变量config,这个config的属性关键字是log4j.configuration,然后给了一个默认值log4j-server.properties,这个变量的主要目的是储存log4j的配置文件地址,默认的文件名是log4j-server.properties,如果在启动时手动设置了其他值的话,那么就会是那个手动设置的值。

    然后首先尝试通过物理地址查找这个配置文件(try中),如果找不到(catch中),那么就到启动时设置的CLASSPATH中去找这个文件。

  6. 再看cassandra-0.8.0的bin版本中的bin文件夹中的cassandra.bat文件(我用的是windows7。。。) ,通过分析这个文件中所作的操作,可以知道如何在Eclipse中配置Cassandra的运行参数。以下摘自cassandra.bat文件。
    if "%OS%" == "Windows_NT" setlocalif NOT DEFINED CASSANDRA_HOME set CASSANDRA_HOME=%~dp0..
    if NOT DEFINED CASSANDRA_MAIN set CASSANDRA_MAIN=org.apache.cassandra.thrift.CassandraDaemon
    if NOT DEFINED JAVA_HOME goto err

    这段分别定义了cassandra的根目录地址,cassandra的入口程序,检查了JAVA_HOME是否定义。

    REM ***** JAVA options *****
    set JAVA_OPTS=^
     -ea^
     -Xms1G^
     -Xmx1G^
     -XX:+HeapDumpOnOutOfMemoryError^
     -XX:+UseParNewGC^
     -XX:+UseConcMarkSweepGC^
     -XX:+CMSParallelRemarkEnabled^
     -XX:SurvivorRatio=8^
     -XX:MaxTenuringThreshold=1^
     -XX:CMSInitiatingOccupancyFraction=75^
     -XX:+UseCMSInitiatingOccupancyOnly^
     -Dcom.sun.management.jmxremote.port=7199^
     -Dcom.sun.management.jmxremote.ssl=false^
     -Dcom.sun.management.jmxremote.authenticate=false^
     -Dlog4j.configuration=log4j-server.properties^
     -Dlog4j.defaultInitOverride=true

    这段是各种参数,需要把这段复制到Eclipse中Run->Debug Configration中建立的Debug项中的VM arguments中(注意把每行最后的^删掉)。

    REM Ensure that any user defined CLASSPATH variables are not used on startup
    set CLASSPATH="%CASSANDRA_HOME%\conf"

    这里就定义了CLASSPATH,原来这里把conf文件夹加入到了CLASSPATH里(CLASSPATH里不止一个地址),怪不得能找到。所以在Eclipse的项目的Properties->Java Build Path->Libraries点Add Class Folder,加入这个conf地址,就不会报错了

    bat文件中其他的设置也是大同小异,就不写了。

2011/06/13 在Eclipse中配置Cassandra

首先,整个过程基本基于下面这篇文章:

原帖地址:http://www.congci.com/item/cassandra-for-eclipse

我们将从svn中下载Cassandra的源代码,完成编译,并执行相应的单元测试。

配置环境

1 安装jdk6,ant。

2 安装Eclipse3.5

3 在Eclipse中安装http://subclipse.tigris.org/update_1.6.x

在Eclipse的菜单选择:Help –> Install New Software

image

接下来,就可以安装subclipse: Add –> 输入名称和地址http://subclipse.tigris.org/update_1.6.x ->勾选所有需要安装的选择

image

最好点击next,安装提示的要求一步一步操作。最后等待subclipse安装完成后重启Eclipse。

下载Cassandra源码

在Eclipse中新建一个svn项目

image

选择:创建新的资源库位置

image

获取svn:https://svn.apache.org/repos/asf/cassandra/tags/cassandra-0.6.2/

image

按照如下选择

image

然后根据提示创建一个Java Project,svn检出操作完成后,我们就可以看到刚刚创建的项目了

image

这样Cassandra的源代码就下载完毕了。

编译Cassandra

假设我们下载的Cassandra源代码的位置在D:\workspace\cassandra-0.6.2,那么我们使用命令行工具在这个目录下执行ant的编译操作。

image

如果编译成功,提示如下:

image

可以看到,执行编译的同时,也生成了thrift,avro和antlr的java源文件。

在Eclipse中编辑Cassandra源码

源代码虽然可以编辑成功,但是我们还是无法利用Cassandra对源代码进行方便的修改。

接下来,要一步一步配置Eclipse,使其可以方便地编辑Cassandra源码。

首先,将D:\workspace\cassandra-0.6.2\lib目录下的所有jar包添加到项目的Build Path中。

image

然后,编辑Src目录的属性,默认的设置为

image

将默认的目录删除,然后添加如下Src目录

image

添加完成之后,目录结构如下

image

按照正常的流程来说,我们对Eclipse的配置就算完成了,可以很方便地在Eclipse中编辑Cassandra源码了。

但是Eclipse还是有一些小Bug可能会影响到正常的功能,比如我遇到的这个情况

image

大家可以看到,GarbageCollectorMXBean其实是jdk中的一个类,但是Eclipse提示找不到定义。处理的办法如下

打开项目的Build Path,先移除JRE System Library

image

然后在将之前移除JRE System Library的添加回来。

image

最后在刷新整个项目,错误提示的问题就解决了。

image

运行单元测试

我们可以将单元测试的代码也添加到Eclipse中。

步骤非常简单:

1 添加JUnit4的jar包

2 添加test目录下的测试代码到Src中。

添加成功后项目的列表如下

image

我们可以直接在test中运行已有的单元测试。

打包发布

当我们完成对Cassandra源码的修改以后,可以将修改后的版本打包发布出来。

使用ant的命令行:ant release

image

执行完毕以后,我们可以在D:\workspace\cassandra-0.6.2\build目录中看到打包后的文件

image

这样,我们就可以使用修改后的Cassandra了。

———————————————————————恶心的分割线————————————————————————

下面是一些我遇到的问题

  1. 之前装了ant(地址:http://apache.etoak.com//ant/binaries/apache-ant-1.8.2-bin.tar.gz),但是没有装svn,所以把整个project下下来之后,ant出错,错误是"Cannot run program "svn":CreateProcess error=2" ,所以还要下个svn,方法见这篇文章https://hycz.wordpress.com/2011/06/13/%E8%BD%ACsvn%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%B7%A5%E5%85%B7%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8windows/
  2.  设置Java Build Path中Source目录,0.8.0版本和0.6.2不太一样,不过无论什么版本,源码目录其实已经写在了build.xml中。以下内容摘自0.8.0版本的build.xml中
    <echo file=".classpath"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
    <classpath>
      <classpathentry kind="src" path="src/java"/>
      <classpathentry kind="src" path="src/gen-java"/>
      <classpathentry kind="src" path="interface/thrift/gen-java"/>
      <classpathentry kind="src" path="drivers/java/src"/>
      <classpathentry kind="src" path="drivers/java/test"/>
      <classpathentry kind="src" path="test/unit"/>
      <classpathentry kind="src" path="test/long"/>
      <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
      <classpathentry kind="output" path="build/classes/main"/>
      <classpathentry kind="lib" path="build/classes/thrift"/>
      <classpathentry kind="lib" path="build/test/classes"/>
      <classpathentry kind="lib" path="test/conf"/>
    ]]>
    	</echo>

    这些目录便是需要在Eclipse中设置的

  3. jar的导入问题,(醒目!!下面的可以用,但是有更简单的设置,开发过程中需要用到的jar包都放在cassandra-0.8.0\build\lib\jars中,直接导入即可),除了将lib文件夹下的jar导入,还有一些其他的jar包不在cassandra目录下。我是在命令行中用ant编译之后才进行的jar导入,在用ant编译的过程中,还自动从网上下载了一些jar文件,我的电脑上是在“C:\Users\用户名\.m2\repository”中,详细的列表可以参见cassandra-0.8.0\build文件夹下的build-dependencies.xml,这个应该是在编译之后产生的。不过显然,更加原始的依赖查询是写在了build.xml中。以下内容摘自0.8.0版本的build.xml中
    <!-- Publish artifacts to Maven repositories -->
      <target name="mvn-install"
              depends="maven-declare-dependencies,artifacts,jar,sources-jar,javadoc-jar"
              description="Installs the artifacts in the Maven Local Repository">
    
        <!-- the parent -->
        <install pomFile="${build.dir}/${final.name}-parent.pom"
                 file="${build.dir}/${final.name}-parent.pom"
                 packaging="pom"/>
    
        <!-- the distribution -->
        <install pomFile="${build.dir}/${final.name}-dist.pom"
                 file="${build.dir}/${final.name}-dist.pom"
                 packaging="pom"/>
        <install pomFile="${build.dir}/${final.name}-dist.pom"
                 file="${build.dir}/${final.name}-bin.tar.gz"
                 packaging="tar.gz"
                 classifier="bin"/>
        <install pomFile="${build.dir}/${final.name}-dist.pom"
                 file="${build.dir}/${final.name}-src.tar.gz"
                 packaging="tar.gz"
                 classifier="src"/>
    
        <!-- the cassandra-thrift jar -->
        <install pomFile="${build.dir}/${ant.project.name}-thrift-${version}.pom"
                 file="${build.dir}/${ant.project.name}-thrift-${version}.jar"/>
        <install pomFile="${build.dir}/${ant.project.name}-thrift-${version}.pom"
                 file="${build.dir}/${ant.project.name}-thrift-${version}-sources.jar"
                 classifier="sources"/>
        <install pomFile="${build.dir}/${ant.project.name}-thrift-${version}.pom"
                 file="${build.dir}/${ant.project.name}-thrift-${version}-javadoc.jar"
                 classifier="javadoc"/>
    
        <!-- the cassandra-all jar -->
        <install pomFile="${build.dir}/${final.name}.pom"
                 file="${build.dir}/${final.name}.jar"/>
        <install pomFile="${build.dir}/${final.name}.pom"
                 file="${build.dir}/${final.name}-sources.jar"
                 classifier="sources"/>
        <install pomFile="${build.dir}/${final.name}.pom"
                 file="${build.dir}/${final.name}-javadoc.jar"
                 classifier="javadoc"/>
    
        <!-- the cassandra-cql jar -->
        <install pomFile="${build.dir}/${ant.project.name}-cql-${cql.driver.version}.pom"
                 file="${build.dir}/${ant.project.name}-cql-${cql.driver.version}.jar"/>
        <install pomFile="${build.dir}/${ant.project.name}-cql-${cql.driver.version}.pom"
                 file="${build.dir}/${ant.project.name}-cql-${cql.driver.version}-sources.jar"
                 classifier="sources"/>
        <install pomFile="${build.dir}/${ant.project.name}-cql-${cql.driver.version}.pom"
                 file="${build.dir}/${ant.project.name}-cql-${cql.driver.version}-javadoc.jar"
                 classifier="javadoc"/>
      </target>
    
      <target name="publish"
              depends="mvn-install"
              if="release"
              description="Publishes the artifacts to the Maven repository">
    
        <!-- the parent -->
        <deploy pomFile="${build.dir}/${final.name}-parent.pom"
                file="${build.dir}/${final.name}-parent.pom"
                packaging="pom"/>
    
        <!-- the distribution -->
        <deploy pomFile="${build.dir}/${final.name}-dist.pom"
                file="${build.dir}/${final.name}-dist.pom"
                packaging="pom"/>
        <deploy pomFile="${build.dir}/${final.name}-dist.pom"
                file="${build.dir}/${final.name}-bin.tar.gz"
                packaging="tar.gz"
                classifier="bin"/>
        <deploy pomFile="${build.dir}/${final.name}-dist.pom"
                file="${build.dir}/${final.name}-src.tar.gz"
                packaging="tar.gz"
                classifier="src"/>
    
        <!-- the cassandra-thrift jar -->
        <deploy pomFile="${build.dir}/${ant.project.name}-thrift-${version}.pom"
                file="${build.dir}/${ant.project.name}-thrift-${version}.jar"/>
        <deploy pomFile="${build.dir}/${ant.project.name}-thrift-${version}.pom"
                file="${build.dir}/${ant.project.name}-thrift-${version}-sources.jar"
                classifier="sources"/>
        <deploy pomFile="${build.dir}/${ant.project.name}-thrift-${version}.pom"
                file="${build.dir}/${ant.project.name}-thrift-${version}-javadoc.jar"
                classifier="javadoc"/>
    
        <!-- the cassandra-all jar -->
        <deploy pomFile="${build.dir}/${final.name}.pom"
                file="${build.dir}/${final.name}.jar"/>
        <deploy pomFile="${build.dir}/${final.name}.pom"
                file="${build.dir}/${final.name}-sources.jar"
                classifier="sources"/>
        <deploy pomFile="${build.dir}/${final.name}.pom"
                file="${build.dir}/${final.name}-javadoc.jar"
                classifier="javadoc"/>
    
        <!-- the cassandra-cql jar -->
        <deploy pomFile="${build.dir}/${ant.project.name}-cql-${cql.driver.version}.pom"
                file="${build.dir}/${ant.project.name}-cql-${cql.driver.version}.jar"/>
        <deploy pomFile="${build.dir}/${ant.project.name}-cql-${cql.driver.version}.pom"
                file="${build.dir}/${ant.project.name}-cql-${cql.driver.version}-sources.jar"
                classifier="sources"/>
        <deploy pomFile="${build.dir}/${ant.project.name}-cql-${cql.driver.version}.pom"
                file="${build.dir}/${ant.project.name}-cql-${cql.driver.version}-javadoc.jar"
                classifier="javadoc"/>
      </target>

    我也是刚刚开始用,估计是编译过程中根据此列表依次检查依赖,如果缺少jar,则从网上下载,下载地址写在了根目录下的build.properties.default文件中,并放在相应的目录中,然后把这些目录名写到build-dependencies.xml中。下载的jar分为两种,一个是源码,一个是编译好的。当我们导入了cassandra-0.8.0\lib下的所有jar之后,会发现还有类找不到,那么这些类就是在这些自动下载的jar中,需要按需要手动在Eclipse中导入。

  4. 待续。。