Cassandra 负载不均衡 与 解决办法

 

最近在看Cassandra,但自打配起一个集群后,负载就不均衡了。

Address Status State Load Owns Token 
134154547520101788379756316570162344774 
10.20.223.115 Up Normal 138.43 KB 32.81% 19836060994110698319501384270720800576 
10.20.223.116 Up Normal 143.39 KB 7.93% 33327637713098975372896733928855304024 
10.20.223.113 Up Normal 143.46 KB 28.38% 81617185997645741434910225007556485361 
10.20.223.114 Up Normal 133.3 KB 3.01% 86736862331839877952832406350985306765 
10.20.223.117 Up Normal 138.43 KB 5.90% 96770512718388865179675126530244922092 
10.20.223.112 Up Normal 138.52 KB 21.97% 134154547520101788379756316570162344774

将 auto_bootstrap 设为 true后,只有一个节点的Token发生了变化。整体均衡度没有明显变化。

由于是初次接触Cassandra,怀疑是否有做过错误的 配置 而未被发现。

于是尝试重新搭建环境、增、删节点,均以失败告终。

也有 朋友 怀疑是数据量少或运行时间少导致的。但我看官方的数据,仅1G数据3个节点都是均衡的,我认为还是配置问题,而且官方介绍负载均衡的算法与Token有关。于是按官方说明手动计算Token:

def tokens(nodes): 
for x in xrange(nodes): 
print 2 ** 127 / nodes * x

然后手动指定(conf/cassandra.yaml) initial_token值,启动后发现Token值并非读取这个配置。应该是头一次启动计算后写入到了 system 空间 里了(system空间中peers表中)。

然后手动更新所有节点的Token值: bin /nodetool -host 10.20.10.31 -port 8080 move 88888888888888888888888888888888888888

注意:Move过程会按新环移动现有数据,完成之后再查看节点信息。神了!虽然当前没有数据,但我已经感觉到问题被解决了:

Address Status State Load Owns Token 
170141183460469231731687303715884105726

10.20.223.111 Up Normal 169.96 KB 14.29% 24305883351495604533098186245126300818 
10.20.223.112 Up Normal 175.13 KB 14.29% 48611766702991209066196372490252601636 
10.20.223.113 Up Normal 175.13 KB 14.29% 72917650054486813599294558735378902454 
10.20.223.114 Up Normal 180.48 KB 14.29% 97223533405982418132392744980505203272 
10.20.223.115 Up Normal 169.93 KB 14.29% 121529416757478022665490931225631504090 
10.20.223.116 Up Normal 175.07 KB 14.29% 145835300108973627198589117470757804908 
10.20.223.117 Up Normal 169.96 KB 14.29% 170141183460469231731687303715884105726

OK,加些数据看看是否均衡吧:

Address Status State Load Owns Token 
170141183460469231731687303715884105726 
10.20.223.111 Up Normal 1.26 GB 14.29% 24305883351495604533098186245126300818 
10.20.223.112 Up Normal 1.26 GB 14.29% 48611766702991209066196372490252601636 
10.20.223.113 Up Normal 1.26 GB 14.29% 72917650054486813599294558735378902454 
10.20.223.114 Up Normal 1.26 GB 14.29% 97223533405982418132392744980505203272 
10.20.223.115 Up Normal 1.26 GB 14.29% 121529416757478022665490931225631504090 
10.20.223.116 Up Normal 1.26 GB 14.29% 145835300108973627198589117470757804908 
10.20.223.117 Up Normal 1.26 GB 14.29% 170141183460469231731687303715884105726

实在是太均衡了,原来就是Token惹的祸!

另外的一篇 文章 

Cassandra之Token

http://www.ningoo.net/html/2010/cassandra_token.html

有一个多月没有更新过blog了,有点惭愧。不管何种理由,不管工作 生活 有何种变动,有一些我们内心真正追求的东西,不能放弃。昨天晚上,世界杯大幕拉开,在等待揭幕战的过程中,看了一段Cassandra关于dht部分的源 代码 。要在生产系统中运维,则数据如何分布不得不做周详细致的考虑。

将Cassandra用于实际的生成环境,一个必须要考虑的关键问题是Token的选择。Token决定了每个节点 存储 的数据的分布范围,每个节点保存的数据的key在(前一个节点Token,本节点Token]的半开半闭区间内,所有的节点形成一个首尾相接的环,所以第一个节点保存的是大于最大Token小于等于最小Token之间的数据。

根据采用的分区策略的不同,Token的类型和设置原则也有所不同。 Cassandra (0.6版本)本身支持三种分区策略:

RandomPartitioner :随机分区是一种hash分区策略,使用的Token是大整数型(BigInteger),范围为0~2^127,因此极端情况下,一个采用随机分区策略的Cassandra集群的节点可以达到2^127+1个节点。嗯,为什么是2^127?因为Cassandra采用了MD5作为hash函数,其结果是128位的整数值(其中一位是符号位,Token取绝对值为结果)。采用随机分区策略的集群无法支持针对Key的范围查询。假如集群有N个节点,每个节点的hash空间采取平均分布的话,那么第i个节点的Token可以设置为:

i * ( 2 ^ 127 / N )

下面的测试 程序 是从org. apache .cassandra.utils.FBUtilities类抽取出来的计算MD5值的函数,输入任何字符都可以得到其对应的MD5的整数值,利用该值和节点的Token对比即可知道该Key对应的数据归属于哪个节点:

OrderPreservingPartitioner :如果要支持针对Key的范围查询,那么可以选择这种有序分区策略。该策略采用的是 字符串 类型的Token。每个节点的具体选择需要根据Key的情况来确定。如果没有指定InitialToken,则系统会使用一个长度为16的随机字符串作为Token,字符串包含大小写字符和数字。

CollatingOrderPreservingPartitioner :和OrderPreservingPartitioner一样是有序分区策略。只是排序的方式不一样,采用的是字节型Token,支持设置不同语言环境的排序方式,代码中默认是en_US。

分区策略和每个节点的Token(Initial Token)都可以在storage-conf.xml 配置文件 中设置:

<Partitioner>org.apache.cassandra.dht.RandomPartitioner</Partitioner>

<InitialToken>10633823966279300000000000000000000000</InitialToken>

节点初始化完成以后,Token值做为元数据会保留在system keyspace中,每次启动会以该值为准,即使再改动配置文件中的InitialToken也不会产生任何影响。

Saved Token found: 10633823966279300000000000000000000000

通过nodetool的ring命令,可以查看集群各个节点的Token,这些Token值最好备份下来,当出现节点彻底顺坏时,可以重新设置同样的Token,确保数据分布可以不受节点损坏的影响。

nodetool -h test ringAddress Status Load Range Ring 85070591730234600000000000000000000000192.168.0.1 Up 0 bytes 10633823966279300000000000000000000000 |<--|192.168.0.2 Up 0 bytes 85070591730234600000000000000000000000 |-->|

PS: 在我的0.6.2的一个测试集群中,使用nodetool时不小心连到了9160端口,结果每次都会把节点搞挂,百试百灵。而且直接telnet到9160端口,随便发送个字符,也会把节点搞崩溃。不知道是我的测试环境的原因,还是Thrift有bug,这样节点的健壮性就有问题了,这个端口只能接受协议格式内的信息。对 Java 和Thrift都不太了解,把这个问题抛出来,希望有大牛能帮忙找到原因。

update : 之前贴的nodetool错连9160端口的报错可能有点误导大家,因为jmx用的默认的8080端口,连9160端口jmx报错是正常的,问题是节点不应该崩溃的。看了/var/log/cassandra/system.log中记录的节点错误信息,报的是OOM,Cassandra的 java 进程都消失了。调整了一下jvm参数,将heap的最小内存从默认的256MB设置到1G(-Xms1G),还是有同样的问题。另外,我的 java 环境是jre1.6.0_18。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值