У меня проблема с консистенцией Кассандры. У меня есть 3 узла Cassandra (версия 2.0.14.352) в кластере, и я читаю и записываю с уровень согласованности QUORUM и мой replicationfactor - это 3. Если я понимаю this прямо в моем случае, Кассандра должна быть последовательной, потому что 2 + 2> 3. Но я написал тест в Java, где я вставить некоторые данные очень быстро в Кассандре с помощью datastax-драйвера:Кассандра не согласуется, несмотря на уровень согласованности QUORUM с коэффициентом репликации 3
final Instant t1 = Instant.parse("2000-01-01T00:00:00.000Z");
final Instant t2 = Instant.parse("2000-02-01T00:00:00.000Z");
for (int i = 0; i < 100; i++) {
dataProvider.setValue(t1, new Double(1));
//If the next line is removed, the test will pass
dataProvider.setValue(t2, new Double(3));
dataProvider.saveToDB();
dataProvider.clear();
assertEquals("i=" + i, new Double(3), dataProvider.getValue(t2));
assertEquals("i=" + i, new Double(1), dataProvider.getValue(t1));
dataProvider.setValue(t1, new Double(2));
dataProvider.saveToDB();
dataProvider.clear();
assertEquals("i=" + i, new Double(2), dataProvider.getValue(t1));
dataProvider.setValue(t1, new Double(101));
dataProvider.saveToDB();
dataProvider.clear();
assertEquals("i=" + i, new Double(101), dataProvider.getValue(t1));
}
с соответствующей таблицей
CREATE TABLE keyspace.table(
id text,
year int,
month int,
time timestamp,
value double,
PRIMARY KEY ((id, year, month), time)
)
dataProvider.setValue() internaly Переводит заданное значение в NavigableMap. dataProvider.saveToDB() вставляет данные в Cassandra. Здесь я попытался, с одной стороны, вставить данные асинхронными и дождаться завершения всех результатов ResultSetFuture, а с другой стороны, я выполнил операторы синхронно. Но это повлияло только на производительность. Подробно метод сохранения выглядит как
final List<ResultSetFuture> sets = newLinkedList();
Batch batch = QueryBuilder.batch();
int batchsize=0;
for (Map.Entry<Instant, Double> entry : valueMap) {
final Instant instant = entry.getKey();
final ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("UTC"));
final Date date = Date.from(instant);
final Insert insert = QueryBuilder.insertInto(table)
.value(ID, id)
.value(YEAR, zonedDateTime.getYear())
.value(MONTH, zonedDateTime.getMonthValue())
.value(TIME, date)
.value(VALUE, entry.getValue());
batch.add(insert);
++batchsize;
if(batchsize % 200 == 0){
sets.add(cassandraConnector.executeAsync(batch));
batch = QueryBuilder.batch();
}
}
if(batchsize % 200 != 0) { //es gibt noch nicht abgeschickte Statements
sets.add(cassandraConnector.executeAsync(batch));
}
cassandraConnector.waitForFinish(sets);
cassandraConnector управляет соединением. Я жду, пока все ResultSets закончил с
public boolean waitForFinish(List<ResultSetFuture> sets) {
ResultSet result = null;
for (final ResultSetFuture resultSetFuture : sets) {
// Wait until finished
try {
result = resultSetFuture.get();
} catch (InterruptedException e) {
resultSetFuture.cancel(true);
e.printStackTrace();
return false;
} catch (ExecutionException e) {
e.printStackTrace();
if (result != null) {
ExecutionInfo executionInfo = result.getExecutionInfo();
System.out.println("Timout from server with IP: " + executionInfo.getTriedHosts());
}
return false;
}
}
return true;
}
Любопытство в том, что если я удалить строку под комментарием, тест будет проходить и это не распространяется того, как часто я исполню ее. Но если я запустил тест, не удаляя строку, иногда он терпит неудачу в первом цикле, но иногда он запускает 3 цикла до тех пор, пока не сработает. Кроме того, он всегда терпит неудачу в разных направлениях. Например
java.lang.AssertionError: i=0
Expected :101
Actual :2
Я также получил
java.lang.AssertionError: i=2
Expected :2
Actual :101
Так что, похоже, что Кассандра написал 1 и после того, что вместо сочинительство 2 Cassandra восстановила 101 я написал до 1. Кто-нибудь есть объяснение для этого поведения? Почему тест проходит, если я удаляю строку? Я пишу по разным разделам. Я попытался изменить уровень согласованности на ВСЕ, но поведение не изменилось.
Можете ли вы также показать код класса DataProvider? – shutty
Я добавил еще код. Там вы можете увидеть, как я создаю и выполняю инструкции. – Julia
Это похоже на общее недопонимание пакетов http://stackoverflow.com/questions/30317877/cassandra-batch-statement-execution-order – RussS