为什么在Cassandra版本0.6.1中不适合使用Binary Memtable的方式导入大量的数据。
在上一篇文章《使 用Binary Memtable将大量数据导入Cassandra》中,讲解了如何使用Binary Memtable将大量数据导入Cassandra。
这一周一直在看如果使用Binary Memtable的方式导入大量的数据。今天看下来,我还是觉得在目前这个版本不适合使用这种方式去导入数据。
原因如下:
- 在0.6+的版本中,Cassandra集群中取消了UDP通信,完全采用TCP监听固定端口(7000)。这种方式导致了2个严重的问题:
1 如果某台机器是Cassandra Server,那么它会绑定7000端口,这个时候我们就无法在本机再次启动使用Binary Memtable方式导入的Client程序了,因为Client程序自身也要绑定7000端口。
2 因为使用Binary Memtable方式导入数据,需要结合MapReduce进行。但是MapReduce可能会在某一台Slave机器中运行多个ReduceTask,这样情况相当于在一台机器上同时启动了多个Client程序,而且每个Client程序都需要绑定7000端口,所以这多个Client程序只有一个可以初始化成功。
- Binary Memtable的运行机制如下:Client端将要导入的数据序列化,然后将序列化后的数据传递给每一个需要改数据的Cassandra Server机器(包括容灾备份的机器),每一台Cassandra Server接收到数据后,先执行反序列化,然后放入内存,当放入内存的数据达到一个量或者是接受到flush操作命令后,执行flush操作,将内存中的数据写入SSTable,将数据持久化到硬盘中。这种方式会导致以下2个问题:
1 由于某一个数据对应的所有机器(包括容灾备份的机器)是在Client端计算出来的,所以Client端会不管Cassandra Server是否可用,将数据发送到所有相关的机器中。当某一个Cassandra Server不可用的时候,那么该不可用的Cassandra Server就不会包含这些数据了。当然,这个问题可以通过后期实际使用的Read Repair操作修复,但是当不可用的机器操作N/2+1的时候,数据就永远无法一致了。
2 我们将某一个数据写入到Cassandra Server后,是不知道Cassandra Server是否真的写入成功,因为接受数据的Cassandra Server没有返回值。具体可以参考sendOneWay和BinaryVerbHandler的实现。
- Cassandra的集群机制如下:每一个Keyspace中的一个key的数据都会对应一台Cassandra Server来存储,同时根据我们配置的容灾备份数据自动选择另外几台Cassandra Server来做容灾。当有一台新的Cassandra Server启动后,之前已经存在所有Cassandra Server都会将这个新启动的Cassandra Server加入自己的token map中,认为整个集群的机器又新增加了一台。以后有相关的数据就会发生到新添加的Cassandra Server中。当某台Cassandra Server不可用的时候,负责容灾备份的机器的机器会将发送给不可用Cassandra Server的数据缓存到自己的STSTEM TABLE中,当其发现之前不可用Cassandra Server启动后,再将STSTEM TABLE中的HINT数据发送过去,完成整个数据备份与恢复的流程。这种方式也会带来一个严重问题:
1 我们启动的Client程序会使用和普通Cassandra Server一样的启动方式,然后加入整个Cassandra集群,这样集群中的其他Cassandra Server会执行数据的负载均衡操作,将备份数据通过Strean的方式传输到Client机器中来。同时由于Client程序并不是正真的Server机器,所以会导致很多Cassandra Server的STSTEM TABLE中缓存大量应该发送给Client机器的数据。
- Cassandra的这个版本自身代码也存在Bug:
1 我们启动Client程序以后无法正常关闭Client程序,后台仍然有线程在执行。这个问题会引起Hadoop MapReduce程序无法正常执行。这个Bug已经修复。
2. Cassandra官网上还有其他的Bug报告。
基于以上这些考虑,决定放弃使用Binary Memtable的方式导入大量数据。
更多关于Cassandra的文章:http://www.cnblogs.com/gpcuster/tag/Cassandra/