我正在使用带有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%。我究竟做错了什么?