Как увеличить счетчик в Кассандре? - PullRequest
8 голосов
/ 24 августа 2010

Я бы хотел использовать Кассандру для хранения прилавка.Например, сколько раз данная страница была просмотрена.Счетчик никогда не уменьшится.Значение счетчика не обязательно должно быть точным, но оно должно быть точным со временем.

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

Еще одна мысль - сохранить загрузку каждой страницы в виде нового столбца.в CF.Тогда я мог бы просто запустить get_count() для этого ключа и получить количество столбцов.Читая документацию , кажется, что это не очень эффективная операция вообще.

Я неправильно подхожу к проблеме?

Ответы [ 5 ]

5 голосов
/ 25 августа 2011

Счетчики добавлены в Cassandra 0.8

Используйте метод incr, чтобы увеличить значение столбца на 1.

[default@app] incr counterCF [ascii('a')][ascii('x')];
Value incremented.
[default@app] incr counterCF [ascii('a')][ascii('x')];
Value incremented.

.Или это может быть сделано программно

CounterColumn counter = new CounterColumn();
ColumnParent cp = new ColumnParent("page_counts_by_minute");
counter.setName(ByteBufferUtil.bytes(bucketByMinute.format(r.date)));
counter.setValue(1);
c.add(ByteBufferUtil.bytes( bucketByDay.format(r.date)+"-"+r.url)
            , cp, counter, ConsistencyLevel.ONE);

Описано здесь: http://www.jointhegrid.com/highperfcassandra/?cat=7

5 голосов
/ 30 августа 2010

[Обновить] Похоже, что поддержка счетчика будет готова к прайм-тайм в 0.8!

Я определенно не буду использовать get_count, так как это операция O (n), которая запускается каждый раз, когда вы читаете "счетчик «.Хуже, чем просто O (n), он может охватывать несколько узлов, что приведет к задержке в сети.И, наконец, зачем связывать все это дисковое пространство, когда все, что вас волнует, это одно число?

На данный момент я бы вообще не использовал Cassandra для счетчиков.Они работают над этой функцией, но она еще не готова к прайм-тайму.

https://issues.apache.org/jira/browse/CASSANDRA-1072

У вас есть несколько вариантов в это время.

1) (Плохо) Сохраните счет в одной записи, и один и только один поток вашего приложения будет отвечать за управление счетчиками.

2) (Лучше) Разделите счетчик на n сегментов и получите управление n потоковкаждый осколок как отдельный счетчик.Вы можете рандомизировать, какой поток используется вашим приложением каждый раз для балансировки нагрузки без учета состояния между этими потоками.Просто убедитесь, что каждый поток отвечает только за один осколок.

3a) (Наилучший) Используйте отдельный инструмент, который либо является транзакционным (он же СУБД), либо поддерживает операции атомарного приращения (memcached, redis).

[Update.2] Я бы не использовал распределенную блокировку (см. Мьютексы memcached и zookeeper), так как это очень нетерпимо к отказу узла или разбиению сети, если он неправильно реализован.

2 голосов
/ 22 сентября 2010

В конечном итоге я использовал get_count () и кешировал результат в кэшируемой семье ColumnFamily.

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

Кроме того, мне удалось отрегулировать, насколько устаревшие данные я готов был принять для каждого запроса.

1 голос
/ 27 мая 2011

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

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

0 голосов
/ 30 августа 2012

Интересно, что я не вижу никого, кто упомянул бы возможность рассчитывать для каждого приложения на компьютере.Скажем, ваше приложение работает на 5 машинах с именами a1, a2, ... a5.Затем вы можете иметь блокировку для каждой машины (т. Е. Файл, который вы открываете с помощью O_EXCL или используете блокировку, чтобы дождаться выполнения других экземпляров с помощью счетчика) и добавить либо одну строку на машину, либо один столбец в зависимости от вашей реализации.Что-то вроде

machine_lock();
this_column_family[machine-name][my-counter] += 1;
machine_unlock();

Таким образом, вы получаете один счетчик на машину.Когда вам нужно общее количество, вы просто читаете a1, a2, ... a5 и суммируете их.

total = 0;
foreach(machines as m) {
  total += this_column_family[m][my-counter];
}

(это псевдокод, который более или менее будет работать с libQtCassandra .)

Таким образом, вы избегаете блокировки, которая блокирует все узлы, и при этом вы все равно получаете безопасный / последовательный подсчет (очевидно, что чтение + сумма не идеальна, и она только дает вам приблизительное значение, но все равноостается последовательным.)

Я не слишком уверен, было бы то же самое, что указал Бен Бернс в отношении наличия n осколков и n нитей, но для меня это не совсем похоже.

А начиная с версии 0.8.x вы можете использовать счетчики Cassandra, что, безусловно, намного проще, хотя может не всегда соответствовать вашим потребностям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...