Как быстро увеличивать счетчики в Кассандре без застоя

У меня есть вопрос Кассандры. Вы знаете, как Cassandra обновляет/увеличивает счетчики?

Я хочу использовать штурмовой болт (CassandraCounterBatchingBolt из репортера storm-contrib на github), который записывается в cassandra. Тем не менее, я не уверен, как работает часть метода incrementCounterColumn(), и есть также ограничения с счетчиками cassandra (от: http://wiki.apache.org/cassandra/Counters), что делает их бесполезными для моего сценария ИМХО:

  • Если запись неожиданно завершается (время ожидания или потеря связи с координатором node), клиент не будет знать, была ли выполнена операция. Повторение может привести к превышению количества CASSANDRA-2495.

  • Удаление счетчика по существу ограничено. Например, если вы очень быстро произвели последовательность "increment, remove, increment", возможно, что удаление будет потеряно

В любом случае, вот мой сценарий:
Я обновляю тот же счетчик быстрее, чем обновления распространяются на другие узлы Cassandra.

Пример:
Скажем, у меня есть 3 узла кассандры. Счетчики на каждом из этих узлов равны 0.
Node1: 0, node2: 0, node3: 0

Приращение приходит: 5 → Node1: 0, node2: 0, node3: 0

Приращение начинается с node 2 - все еще нужно распространять на node1 и node3
Node1: 0, node2: 5, node3: 0

Тем временем, еще один прирост до предыдущего приращения: 3 → Node1: 0, node2: 5, node3: 0

Предполагая, что 3 начинается с другого node, чем в начале 5, мы имеем:
Node1: 3, node2: 5, node3: 0

Теперь, если 3 передается другим узлам AS IN INCREMENT, а не как новое значение (и то же самое для 5), то в конечном итоге узлы будут равны 8, и это то, что я хочу.

Если 3 перезаписывает 5 (потому что имеет более позднюю временную метку), это проблематично - не то, что я хочу.

Знаете ли вы, как эти обновления/приращения обрабатываются Cassandra?

Обратите внимание, что чтение перед записью по-прежнему подвержено той же самой проблеме, в зависимости от которой реплика node выполняется чтение (кворум все равно может завершиться неудачей, если распространение не далеко)

Я также думаю, что, возможно, ставить кеш-бет/ш мой штурмовой болт, и Кассандра может решить эту проблему, но это история в другое время.

Ответы

Ответ 1

Счётчики в C * имеют сложное внутреннее представление, которое позволяет избежать большинства (но не всех) проблем подсчета вещей в безликой распределенной системе. Мне нравится думать о них как о закрытых прилавках. Счетчик состоит из нескольких подзаголовков, идентифицированных идентификатором хоста и номером версии. Хост, который принимает операцию счетчика, увеличивает свой собственный счетчик, а также увеличивает версию. Затем он реплицирует все свое состояние счетчика на другие реплики, которые объединяют его со своими состояниями. Когда счетчик считывается, обработка операции чтения node определяет значение счетчика, суммируя общее количество отсчетов с каждого хоста.

В каждом node приращение счетчика похоже на все остальное в Cassandra, просто написание. Приращение записывается в таблицу заметок, а локальное значение определяется во время чтения путем слияния всех приращений из таблицы памяти и всех SSTables.

Я надеюсь, что это объяснение поможет вам поверить мне, когда я говорю, что вам не нужно беспокоиться об увеличении счетчиков быстрее, чем может справиться Cassandra. Поскольку каждый node хранит свой собственный счетчик и никогда не реплицирует операции с приращением, нет возможности потерять счеты по условиям гонки, например, как сценарий чтения-изменения-записи. Если Кассандра согласится на запись, вы почти гарантируете, что она будет считаться.

То, что вам не гарантировано, заключается в том, что подсчет будет отображаться правильно в любое время, если только. Если приращение записывается в один node, но значение счетчика, считанное с другого сразу после этого, не гарантируется, что приращение было реплицировано, и вам также нужно учитывать, что произойдет во время сетевого раздела. Это более или менее то же самое с любой записью в Cassandra, это в ее последовательной природе, и это зависит от того, какие уровни согласованности вы использовали для операций.

Существует также возможность потерянного подтверждения. Если вы делаете приращение и теряете соединение с Cassandra, прежде чем вы сможете получить ответ, вы не сможете узнать, получилась ли ваша запись. И когда вы получите соединение обратно, вы не можете сказать, так как вы не знаете, что счет был до того, как вы увеличили. Это неотъемлемая проблема с системами, которые выбирают доступность по сравнению с последовательностью, и ценой, которую вы платите за многие другие преимущества.

Наконец, проблема быстрого удаления, приращения, удаления является реальной и что-то, чего вам следует избегать. Проблема в том, что операция приращения существенно воскресит столбец, и если эти операции будут достаточно близки друг к другу, они могут получить одну и ту же метку времени. Кассандра - это строго последняя победа и определяет последний, основанный на отметке времени операции. Если две операции имеют один и тот же штамп времени, выигрывает "больше", что означает тот, который сортируется в строгом порядке байтов. Это реально, но я бы не слишком беспокоился об этом, если вы делаете очень быстрые записи и не удаляете их до одного значения (что, вероятно, является ошибкой в ​​вашей модели данных).

Вот хорошее руководство для внутренних счетчиков Cassandra: http://www.datastax.com/wp-content/uploads/2011/07/cassandra_sf_counters.pdf

Ответ 2

Текущая версия счетчиков просто не подходит для использования, которая требует гарантий без перерасчета и непосредственной согласованности.

Существуют операции с приращением и уменьшением, и они не будут сталкиваться друг с другом, и, запрещая любые потерянные мутации или переизданные мутации, даст вам правильный результат.

Возможно, вам будет интересно переписать счетчики Cassandra (https://issues.apache.org/jira/browse/CASSANDRA-6504), и он должен решить все текущие проблемы с получением правильный счет.

В то же время, если бы мне пришлось реализовать это поверх текущей версии Cassandra, и точное подсчет был существенным, я бы, вероятно, сохранил каждый прирост или декремент в качестве столбца и сделал агрегацию результатов для чтения, в то время как запись контрольной точки, поэтому вам не нужно читать до начала времени, чтобы рассчитать последующие результаты.

Это добавляет большую нагрузку на сторону чтения, хотя это чрезвычайно эффективно на пути записи, поэтому может или не может работать для вашего использования.

Ответ 3

Чтобы понять обновления/приращения, например, операции записи, я предлагаю вам пройти через Gossip, протокол, используемый Cassandra для связи. В Gossip каждый участник (node) поддерживает свое состояние, используя кортеж σ(K) = (V*N), где σ(K) - это состояние ключа K с V значением и N как номер версии.

Чтобы поддерживать единую версию правды для пакета данных, Gossip поддерживает механизм примирения, а именно Precise и Scuttlebutt (current). Согласно Scuttlebutt Reconciliation, перед обновлением любого кортежа они обмениваются данными друг с другом, чтобы проверить, кто держит самую высокую версию (новейшее значение) ключа. Тот, кто держит самую высокую версию, отвечает за операцию записи.

Для получения дополнительной информации прочтите статью .