Я использую драйвер datastax java 3.1.0 для подключения к кластеру cassandra, а версия кластера cassandra - 2.0.10. Я пишу асинхронно с консистенцией QUORUM.
private final ExecutorService executorService = Executors.newFixedThreadPool(10);
public void save(String process, int clientid, long deviceid) {
String sql = "insert into storage (process, clientid, deviceid) values (?, ?, ?)";
try {
BoundStatement bs = CacheStatement.getInstance().getStatement(sql);
bs.setConsistencyLevel(ConsistencyLevel.QUORUM);
bs.setString(0, process);
bs.setInt(1, clientid);
bs.setLong(2, deviceid);
ResultSetFuture future = session.executeAsync(bs);
Futures.addCallback(future, new FutureCallback<ResultSet>() {
@Override
public void onSuccess(ResultSet result) {
logger.logInfo("successfully written");
}
@Override
public void onFailure(Throwable t) {
logger.logError("error= ", t);
}
}, executorService);
} catch (Exception ex) {
logger.logError("error= ", ex);
}
}
Мой метод сохранения будет вызываться из нескольких потоков с очень высокой скоростью.
Вопрос:
Я хочу отключить запрос к методу executeAsync
, который пишет асинхронно в Cassandra. Если я напишу с очень высокой скоростью, чем может работать кластер Cassandra, тогда он начнет метать ошибки, и я хочу, чтобы все мои записи успешно переходили в cassandra без каких-либо потерь.
Я видел этот пост, где решение должно использовать Semaphore
с фиксированным количеством разрешений. Но я не уверен, как и как лучше всего это реализовать. Раньше я никогда раньше не использовал Семафор. Это логика. Может ли кто-нибудь представить пример с базой Семафора в моем коде или если есть лучший способ/вариант, тогда дайте мне знать также.
В контексте написания программы dataloader вы можете что-то сделать например:
- Чтобы упростить использование Семафора или какой-либо другой конструкции с фиксированным количеством разрешений (это будет ваше максимальное количество потоков Запросы). Всякий раз, когда вы отправляете запрос с помощью executeAsync, получить разрешение. Вам действительно нужно только 1 нить (но может понадобиться ввести пул размером ядра # cpu, который делает это), который приобретает разрешения от Семафора и выполняет запросы. Это будет просто блок на приобретение, пока не будет доступного разрешения.
- Используйте Futures.addCallback для будущего, возвращаемого с executeAsync. Обратный вызов должен вызывать Sempahore.release() как в onSuccess, так и в onFailure случаях. Отпустив разрешение, это должно позволить вашей теме в шаге 1 продолжить и отправить следующий запрос.
Также я видел пару других сообщений, где они говорили об использовании RingBuffer
или Guava RateLimitter
, и какой из них лучше, и я должен использовать? Ниже приведены варианты, которые я могу придумать:
- Использование семафора
- Использование кольцевого буфера
- Использование ограничителя скорости Guava
Может ли кто-нибудь помочь мне с примером того, как мы можем дросселировать запрос или получить противодавление для записи cassandra и убедиться, что все записи успешно переходят в cassandra?