为什么cassandra集群写入没问题,但更新总是失败(约30%)?

时间:2015-05-12 04:47:44

标签: cassandra-2.0 datastax-java-driver

我正在使用带有4个节点(Amazon)的Cassandra Cluster,我有复制因子= 2的test_ks_r2,写入和更新,一致性级别= ALL,读取时的一致性级别= ONE。代码使用的是datastax java驱动程序(版本2.1.5):

    // schema of user column family
    CREATE TABLE user (
        id text PRIMARY KEY,
        password text,
        username text
    );


    // ResultSet class
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Objects;
    import java.util.HashMap;
    import java.util.Map;

    public class ResultSet {
      private List<String> idList = new ArrayList<String>();
      private Map<String, List<String>> data = new HashMap<String, List<String>>();

      public void setIdList(List<String> v) {idList = v;}
      public List<String> getIdList() { return idList;}

      public void setData(Map<String, List<String>> v) {data = v;}
      public Map<String, List<String>> getData() {return data;}
    }

    // test cassandra class
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Objects;
    import java.util.HashMap;
    import java.util.Map;

    import com.datastax.driver.core.*;
    import com.datastax.driver.core.Cluster.Builder;
    import com.datastax.driver.core.querybuilder.QueryBuilder;

    class TestCassandra {
        private ConsistencyLevel getConsistencyLevel(String consistency) {
          System.out.println("consistency level string: " + consistency);
          if(consistency.equals("one")) {
              System.out.println("using consistency level: ONE");
              return ConsistencyLevel.ONE;
          }
          else if(consistency.equals("two")) {
              System.out.println("using consistency level: TWO");
              return ConsistencyLevel.TWO;
          }
          else if(consistency.equals("quorum")) {
              System.out.println("using consistency level: QUORUM");
              return ConsistencyLevel.QUORUM;
          }
          else if(consistency.equals("all")) {
              System.out.println("using consistency level: ALL");
              return ConsistencyLevel.ALL;
          }
          else {
              System.out.println("using default consistency level: ONE");
              return ConsistencyLevel.ONE;
          }
      }

      public void testWriteUpdateRead(int n, String mode, int delay) {
          if (mode.equals("QueryBuilder")) {                
              System.out.println("test write & read with QueryBuilder ...");    
          } else if (mode.equals("PreparedStatement")) {
              System.out.println("test write & read with PreparedStatement ...");
          } else {
              System.exit(-1);
          }

          ResultSet resultSet = write(n, mode, getConsistencyLevel("all")); 
          read(resultSet.getIdList(), resultSet.getData(), getConsistencyLevel("one"));
          // update data
          update(resultSet, mode, getConsistencyLevel("all"), delay);
          // read again
          read(resultSet.getIdList(), resultSet.getData(), getConsistencyLevel("one"));
      }  

      public ResultSet update(ResultSet resultSet, String mode, ConsistencyLevel consistencyLevel, int delay) {
          PreparedStatement ps = session.prepare("UPDATE user SET password = ? WHERE id = ?")
                                  .setConsistencyLevel(consistencyLevel);
          List<String> idList = resultSet.getIdList();
          Map<String, List<String>> data = resultSet.getData();

          for (String idRead: idList) {
              try {
                  Thread.sleep(delay);
              }
              catch (Exception e) {
                  System.out.println(e);
              }
              String newPassword = "new password" + idRead;

              if (mode.equals("QueryBuilder")) {
                  session.execute(
                              QueryBuilder.update("user")
                                  .where(QueryBuilder.eq("id", idRead))
                                  .with(QueryBuilder.set("password", newPassword))
                                  .setConsistencyLevel(consistencyLevel)
                          );

              } else  {
                  ResultSet result = session.execute(ps.bind(newPassword, idRead));
                  System.out.println(result);
              }

              List<String> itemValues = new ArrayList<String>();
              itemValues.add("empty");
              itemValues.add(newPassword);
              data.put(idRead, itemValues);
          }

          System.out.println("Update " + Objects.toString(idList.size(), null) + " times");
          resultSet.setData(data);
          return resultSet;
      }    

      public ResultSet write(int n, String mode, ConsistencyLevel consistencyLevel) {
          PreparedStatement ps = session
                                  .prepare("INSERT INTO user (id, username, password) VALUES (?, ?, ?)")
                                  .setConsistencyLevel(consistencyLevel);

          String idWrite = "";                        
          List<String> idList = new ArrayList<String>();
          Map<String, List<String>> data = new HashMap<String, List<String>>();

          for (int i=0; i<n;i++) {
              idWrite =  Objects.toString(System.currentTimeMillis(),null);
              String username = "username" + idWrite;
              String password = "password" + idWrite;



              List<String> itemValues = new ArrayList<String>();
              itemValues.add(username);
              itemValues.add(password);

              if (mode.equals("QueryBuilder")) {
                  session.execute(
                              QueryBuilder.insertInto("user")
                                  .value("id", idWrite)
                                  .value("username", username)
                                  .value("password", password)
                                  .setConsistencyLevel(consistencyLevel)
                              );

              } else  {
                  session.execute(ps.bind(idWrite, username, password));
              }   
              idList.add(idWrite);
              data.put(idWrite, itemValues);
          }

          ResultSet resultSet = new ResultSet();
          resultSet.setIdList(idList);
          resultSet.setData(data);

          System.out.println("Write " + Objects.toString(n, null) + " times");
          return resultSet;
      }   

      public void read(List<String> idList, Map<String, List<String>> data, ConsistencyLevel consistencyLevel) {
          int readCount;
          int success = 0;
          for (String idRead: idList) {
              PreparedStatement stmt = session.prepare("SELECT * FROM user WHERE id = ?").setConsistencyLevel(consistencyLevel);
              List<String> itemValues = data.get(idRead);
              try {
                  readCount = 0;
                  Row resultRow = null; 
                  for (Row row : session.execute(stmt.bind(idRead))) {
                      readCount++;
                      resultRow = row;
                  }

                  // there should be only 1 read, in such case, this is a successful read of a recent write
                  if (readCount==1) {
                      if(itemValues.get(1).equals(resultRow.getString("password"))) {
                          success++;    
                      } else {
                          System.out.println("password: " + itemValues.get(1));
                          System.out.println("password in database: " + resultRow.getString("password"));
                      }
                  }

              } catch (Exception e) {
                  success = success + 0;  // do not increase success since there is an exception
              }
          }


          System.out.println("Successfully read back " + Objects.toString(success, null) + " times");
      } 
    }

这是我的结果

    Write 40 times
    consistency level string: one
    using consistency level: ONE
    Successfully read back 40 times
    consistency level string: all
    using consistency level: ALL
    Update 40 times
    consistency level string: one
    using consistency level: ONE
    Successfully read back 32 times

更新总是失败约30%。我究竟做错了什么?

0 个答案:

没有答案