这里,我们开始搭建一个cassandra集群。
一、了解token
token是cassandra里相当重要的一个概念,它是cassandra用来平衡集群内各节点负载的一个属性。cassandra里有不同的token分配策略,推荐采用默认的RandomPartitioner分区策略。在这个策略下,token是一个0~2的127次方之间的一个整数(这也意味着理论上cassandra可以支持2的127次方个节点)。之所以是2的127次方,是因为MD5 HASH固定输出128位的数,去掉一位符号位,剩下127位。
cassandra会将你插入数据时的key进行md5 HASH,得到一个127位的数,然后将这个数与各节点的token比较来决定存储到哪个节点上。它根据以下规则进行节点选择:
1.数据将存储到拥有最近的比key的hash值大的token的节点上;
2.若key的hash值比最大的token大,那将被存储到具有最小token的节点上。
在配置文件cassandra.yaml里,有一个配置是initial_token,这里就是配置该节点的token值。该值留空时,cassandra会自动给该节点分配一个token,依据以下规则:
1.若该节点已经被配置好准备加入集群,则cassandra会根据集群现有的token来分配一个最平衡的token给该节点。很明显,分配一个token给新加入的节点,会让现有的某个节点减少一半的负载。若集群里有多个token都是一样平衡, 则它会选择一个可以分担目前存储了最多数据的节点的token。
2.若该节点还未准备好加入集群,则cassandra会认为这个节点是引导节点,并分配一个固定值给它。所以若你分别单独配置两台节点,然后再尝试将它们集群,则会报告token重复。最好的方法应该是先单独配置第一台节点作为引导节点,然后后面的节点配置时应该也同时配置加入集群(后文说明),这样它们会自动获得一个平衡的token。
配置文件里的token仅在系统第一次启动时被使用,然后该值被写入system文件,以后系统启动将不再从配置文件读取token。因此若你发现两台节点的token重复,你无法通过改变配置文件里的token来改变节点的token。正确的修改方法是删除自定义data文件夹里的所有文件,重新启动服务。
token会直接影响集群里节点所承受的负载,我们应该尽量保证每个节点所负责的token范围是平衡的。若你发现节点的负载不平衡,你可以手动改变它们的token来让它们平衡。先计算出每台节点的token(平均分配),然后使用nodetool工具改变它。下面给出一个java里计算token的方法,参数是节点数。
public static void calToken(int nodesNum)
{
DecimalFormat df = new DecimalFormat(".");
for(int i = 0;i < nodesNum;i++)
{
System.out.println(df.format((i * Math.pow(2, 127) / nodesNum)));
}
}
得到token后,使用nodetool来手动分配,比如我要将地址为192.168.20.1的节点的token改变为56713727820156410000000000000000000000:
nodetool.bat -h 192.168.20.1 move 56713727820156410000000000000000000000
二、修改配置文件
讲完了token,现在来说一下集群应该怎么配置。配置文件的修改依然集中在cassandra.yaml文件里,主要修改以下属性:
cluster_name:集群名,所有集群里的节点,这个配置必须相同。
seeds:这是种子节点。cassandra是一个p2p式的分布式数据库,没有所谓的中心节点。但为了保证节点能找到集群,你必须告诉它至少一台已经在集群内的节点IP。这样通过这个节点,它能找到集群内的所有节点。
listen_address:其它节点与自己通信的IP,这里必须设置为自己的主机IP。若设置为localhost或127.0.0.1,则可能其它节点无法与自己通信。
rpc_address:这里设置其它节点上的客户端能否与自己的服务端通信。设置为0.0.0.0表示任何节点上的客户端都可以与自己通信,否则只允许本机客户端与自己通信。
这里以两台机器A和B示例,它们的IP分别为192.168.20.1和192.168.20.2。
A的配置如下:
cluster_name:'FirstCluster'
seeds: "192.168.20.1,192.168.20.2"
listen_address: 192.168.20.1
rpc_address: 0.0.0.0
B的配置如下:
cluster_name:'FirstCluster'
seeds: "192.168.20.2,192.168.20.1"
listen_address: 192.168.20.2
rpc_address: 0.0.0.0
其实A和B的seeds配置没必要都一样,只要有其中一个配置了对方的IP,保证他们可以互相通信就可以了。因此若我们想再加入一台节点C,则我们只需要在C的seeds里加上A或B的IP就可以了,A和B的seeds不需要变。但官网推荐seeds都配置成一样的,因为这样会更健壮。假如C只写了A的IP,那么若A断了,则B和C也断了。因此可以的话,尽量将集群里所有节点的seeds配置成一样的。
三、启动集群
将这几台机器启动后,若以上配置正确,它们会自动探测到对方并完成集群。为了查看是否正确集群,我们进入bin目录使用ring命令:
nodetool.bat -h localhost ring
若集群完成,会输出集群内所有机器的信息。DC表示它们所在的数据中心,Status表示目前是否在线,State表示该节点的数据库是否正常,Load表示当前该节点所存储的数据的大小,Owns表示根据Token计算的预计数据负载。
四、一些常用的操作
集群里,数据会自动分布到对应的节点上,但我们可能想数据存储多个副本,那么可以设置replication_factor属性。replication_factor表示一个数据存放多少个副本,以前该属性可以在配置文件里修改,但最新的cassandra取消了这个做法,你需要启动客户端来修改。进入bin,打开客户端cassandra-cli:
connect localhost/9160;
use DEMO;
update keyspace DEMO with placement_strategy = 'org.apache.cassandra.locator.SimpleStrategy' and strategy_options={replication_factor:3};
这条语句,首先将placement_strategy从默认的NetworkTopologyStrategy修改为SimpleStrategy,然后我们才能设置replication_factor属性。
修改完成后,数据将会自动存储多个副本在不同的节点上,第一个数据副本存储在最适合的token节点上,第二个副本的节点选择将按照第一个的token递增。
但这个同步并不是立刻完成的,若你想立刻看它们散布副本,可以对所有节点使用repair命令。
nodetool.bat -h <ip> repair
此时再使用ring命令,就会发现节点的Load应该都增多了。
若集群里有新节点加入,则它们会分掉一部分的token范围,但原来已经分配好的数据却可能不会随着新token而重新分布(这里说的是集群自动分配token,如果你使用了move命令手动重新分配了token,则数据也会随之重新分布)。若你想让它们重新分布,则在加入新节点后,使用repair命令,它们会自动去索引自己的数据。而此时老节点上又存在一些不属于自己的数据,我们可以使用cleanup命令来清除冗余数据:
nodetool.bat -h <ip> cleanup
注意,你最好确认新机器可以正常工作后再使用这个命令。