我们的集群是双节点集群,机器配置比较垃圾,都是2个Linux VM.

具体配置为:

cpu信息:在 /proc/cpuinfo

内存信息:在/proc/meminfo

 

我们用最基本的Cassandra thrift API 来实现插入50万条记录到这个Cassandra集群的负载。为了公平起见,我们不去设置备份,也就是把repliaction因子设为1,这样它不需要额外的写副本的开销:

最终代码如下:

下面的类是工具类,因为在信息实际存在Cassandra内存中,所以这个工具类负责在内存和字符串之间转换:

 
  
  1. /*  
  2.  */ 
  3. package com.charles.cassandra.util; 
  4.  
  5. import java.io.UnsupportedEncodingException; 
  6. import java.nio.ByteBuffer; 
  7.  
  8. /** 
  9.  * 
  10.  * Description: 这个类提供了一些Cassandra操作的工具类 
  11.  * 
  12.  * @author charles.wang 
  13.  * @created May 19, 2012 11:18:27 AM 
  14.  *  
  15.  */ 
  16. public class CassandraOperationUtil { 
  17.      
  18.     /** 
  19.      *因为在Cassandra中,信息都存在内存的,所以都是以ByteBuffer形式存储的,但是ByteBuffer对于人类来说没有String可读性强 
  20.      *所以这个方法可以吧字符串转为ByteBuffer 
  21.      */ 
  22.     public static ByteBuffer stringToByteBuffer(String s) throws UnsupportedEncodingException{ 
  23.          
  24.         return ByteBuffer.wrap(s.getBytes("UTF-8")); 
  25.     } 
  26.      
  27.     /** 
  28.      *因为在Cassandra中,信息都存在内存的,所以都是以ByteBuffer形式存储的,但是ByteBuffer对于人类来说没有String可读性强 
  29.      *所以对称的,这个方法吧ByteBuffer转为人类可读的字符串 
  30.      */ 
  31.     public static String byteBufferToString (ByteBuffer b) throws UnsupportedEncodingException{ 
  32.          
  33.         //先构建一个字节数组 
  34.         byte[] bytes = new byte[b.remaining()]; 
  35.         //吧bytebuffer里面的内容全部存入字节数组 
  36.         b.get(bytes); 
  37.         //然后把这些bytes转为String 
  38.         return new String(bytes,"UTF-8"); 
  39.     } 
  40.  

下面是真正的压力测试类:

 
  
  1. package com.charles.cassandra.demo; 
  2.  
  3. import java.io.UnsupportedEncodingException; 
  4. import java.nio.ByteBuffer; 
  5. import java.util.List; 
  6.  
  7. import org.apache.cassandra.thrift.Cassandra; 
  8. import org.apache.cassandra.thrift.Column; 
  9. import org.apache.cassandra.thrift.ColumnOrSuperColumn; 
  10. import org.apache.cassandra.thrift.ColumnParent; 
  11. import org.apache.cassandra.thrift.ConsistencyLevel; 
  12. import org.apache.cassandra.thrift.InvalidRequestException; 
  13. import org.apache.cassandra.thrift.NotFoundException; 
  14. import org.apache.cassandra.thrift.TBinaryProtocol; 
  15. import org.apache.cassandra.thrift.TimedOutException; 
  16. import org.apache.cassandra.thrift.UnavailableException; 
  17. import org.apache.thrift.TException; 
  18. import org.apache.thrift.protocol.TProtocol; 
  19. import org.apache.thrift.transport.TFramedTransport; 
  20. import org.apache.thrift.transport.TSocket; 
  21. import org.apache.thrift.transport.TTransport; 
  22.  
  23. import com.charles.cassandra.util.CassandraOperationUtil; 
  24.  
  25. public class CassandraClusterStressTest 
  26.     public static void main(String[] args) 
  27.         throws TException, InvalidRequestException,          
  28.         UnavailableException, UnsupportedEncodingException, 
  29.         NotFoundException, TimedOutException 
  30.     { 
  31.         //包装好的socket 
  32.         TTransport tr = new TFramedTransport(new TSocket("192.168.129.34",9160)); 
  33.         TProtocol proto = new TBinaryProtocol(tr); 
  34.         Cassandra.Client client = new Cassandra.Client(proto); 
  35.         tr.open(); 
  36.          
  37.         if(!tr.isOpen()) 
  38.         { 
  39.             System.out.println("无法连接到服务器!"); 
  40.             return
  41.         } 
  42.          
  43.         System.out.println("开始压力测试,我们插入50W条数据到2节点集群中"); 
  44.         System.out.println("..."); 
  45.          
  46.         //标记开始时间 
  47.         long startTime = System.currentTimeMillis(); 
  48.          
  49.         client.set_keyspace("Charles_Stress_Test");//使用Charles_Stress_Test keyspace 
  50.         ColumnParent parent = new ColumnParent("student");//column family 
  51.          
  52.         /* 
  53.          * 这里我们插入50万条数据到Student内 
  54.          * 每条数据包括id和name 
  55.          */ 
  56.         String key_user_id = "a"
  57.         for(int i = 0;i < 500000;i++) 
  58.         { 
  59.             String k = key_user_id + i;//row key 
  60.             long timestamp = System.currentTimeMillis();//时间戳 
  61.              
  62.             //每行的第一个字段(id字段) 
  63.             Column idColumn = new Column(CassandraOperationUtil.stringToByteBuffer("id"));//字段名 
  64.             idColumn.setValue(CassandraOperationUtil.stringToByteBuffer(i + ""));//字段值 
  65.             idColumn.setTimestamp(timestamp);//时间戳 
  66.             client.insert( 
  67.                 CassandraOperationUtil.stringToByteBuffer(k),  
  68.                 parent,  
  69.                 idColumn,  
  70.                 ConsistencyLevel.ONE); 
  71.              
  72.             //每行的第二个字段(name字段) 
  73.             Column nameColumn = new Column(CassandraOperationUtil.stringToByteBuffer("name")); 
  74.             nameColumn.setValue(CassandraOperationUtil.stringToByteBuffer("student" + i)); 
  75.             nameColumn.setTimestamp(timestamp); 
  76.             client.insert( 
  77.                 CassandraOperationUtil.stringToByteBuffer(k),  
  78.                 parent,  
  79.                 nameColumn,  
  80.                 ConsistencyLevel.ONE); 
  81.         } 
  82.        
  83.         //标记结束时间 
  84.         long endTime = System.currentTimeMillis(); 
  85.         //标记一共用时 
  86.         long elapsedTime = endTime-startTime; 
  87.          
  88.         System.out.println("压力测试完毕,用时: "+elapsedTime+" 毫秒"); 
  89.         
  90.         //关闭连接 
  91.         tr.close(); 
  92.     } 
  93.      
  94.     

最终压力测试执行完毕,结果如下:

我们验证下结果,我们打开opscenter->DATA EXPLORER,然后我们搜索最后一条记录,看是否存在:

所以我们相信这些数据已经存在在Cassandra 集群中了。

 

所以,我们看到,在低配置的机器上(Linux VM),就算插入50W条数据也需要672.5秒,也就是11分钟多,也不是很强大嘛!

 

等会我会对比在关系数据库Oracle中插入50W条记录,来对比下性能。