2017-02-06 5 views
0

Я пытаюсь создать службу таймсеров на основе Cassandra, которая будет отслеживать некоторые данные журнала. В базе данных будет наблюдаться относительно большой объем записей (ожидающих ~ 500 мил вставки/день) и менее частые, но большие объемы чтения (подумайте, что один день данных или один месяц данных).Моделирование временных рядов Cassandra

Упрощенная модель данных одной записи журнала выглядит следующим образом (в действительности она имеет 50 или около колонка):

log_datetime date 
log_some_field text 
log_some_other_field text 

Наиболее читаемых запросы будут вращаться вокруг выбора данных из определенного диапазона дат, всегда упорядоченных по убыванию по дате. (например, SELECT * FROM logs WHERE log_datetime >= 2012-01-01 and log_datetime <= 2012-02-01 ORDER BY log_datetime DESC). Это, как правило, занимает значительное количество времени, поэтому я бы хотел как можно больше оптимизировать его.

Как упорядочивания и фильтрации по сегодняшний день являются наиболее важными особенностями, пока записи не так уж и страшно, то первая мысль была что-то вроде этого (где log_day является день года) определение:

CREATE TABLE logs(
    log_day tinyint 
    log_datetime timeuuid 
    log_some_field text 
    log_some_other_field text 
    PRIMARY KEY (log_day, log_datetime) 
    WITH CLUSTERING ORDER BY (log_datetime DESC) 
) 

Насколько я понимаю, это приведет к тому, что поиск будет таким же хорошим, как и при заказе данных, и один раздел потребуется для восстановления в один день (я могу обработать на клиенте случаи, когда выбрано несколько дней). Однако это приведет к тому, что записи перейдут на один сервер, что значительно повлияет на производительность записи. Другой вариант - выбрать какой-либо случайный набор, который будет использоваться в качестве ключей разделов, и распределять их по кругу с клиента, что сделает записи более быстрыми и масштабируемыми, но приведет к ухудшению производительности чтения, особенно если нам придется повторно сортировать данные. Большинство примеров, которые я видел, обычно имеют естественные ключи раздела в наборе данных, такие как user_id или post_id, что не является моим делом.

У кого-нибудь здесь есть аналогичная информация? Если да, то какие компромиссы вы выполняли, чтобы добиться достойной производительности? Знаете ли вы о каких-либо базах данных, которые бы лучше работали в таких случаях?

ответ

1

Как вы заметили, использование дня в качестве ключа раздела означает, что записи переходят на один первичный узел в течение всего дня. Данные копируются в Cassandra на основе коэффициента репликации, как правило, 3. Таким образом, три узла будут записаны в любой день.

Если объем данных был низким, это может быть приемлемым. Как правило, это не так, и можно использовать какой-то ведро времени, например, 5 или 10-минутные интервалы, рассчитанные в приложении.

CREATE TABLE logs(
    log_day tinyint 
    timebucket tinyint 
    log_datetime timeuuid 
    log_some_field text 
    log_some_other_field text 
    PRIMARY KEY ((log_day, timebucket) log_datetime) 
    WITH CLUSTERING ORDER BY (log_datetime DESC) 
) 

Выбор подходящего временного интервала для ведра зависит от ожидаемого объема данных. С 500M пишет в день, то есть около 6K в секунду. Ваши ведра времени могут быть завершены в течение часа, так что у вас будет всего 6 (используя 10 минут) или весь день, имея 144 уникальных ведра. При чтении результатов ваше приложение должно будет прочитать все ведра за данный день и слить (но не сортировать) результаты.

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

+0

С ведром времени мы все равно увидим некоторое неравномерное распределение или мне что-то не хватает (например, один сервер получит все запросы в течение 5 минут)? Может ли дескриптор одного узла Cassandra обрабатывать ~ 10k req/second или было бы лучше просто сделать раунд robin в клиентском приложении? – woland

+0

Да, он будет записывать данные в первичный узел на время ведра времени, например 5 минут. Вы можете сделать это как можно меньше.Альтернативно, используйте что-то вроде минут% 10, чтобы создать 10 ведер, которые каждую минуту вращаются между узлами. Ваше оборудование действительно определит, будет ли 10k/sec устойчивой пропускной способностью или нет. – Bradski

Смежные вопросы