Алексей Чумаков. apache cassandra на реальном проекте
TRANSCRIPT
Алексей Чумаков[email protected]: alexey.chumakov
Вкратце
• Немного о NoSQL вцелом
• Что такое Apache Cassandra и для чего она может понадобиться
• Как она устроена изнутри
• Несколько примеров
• Нюансы...
• Администрирование
НЕМНОГО О NOSQL…
NoSQL. Зачем?
Join, group by, count начинают работать медленно на больших объемах данных
BigData – данных много (не помещаются на один сервер) и они все нужны
Необходима репликация данных между датацентрами и их постоянная доступность (availability)
Partitioning/sharding вручную не всегда удобен
А еще хотим гибкую схему данных...
NoSQL. Зачем?
Pull on Demand vs Push on Change
CAP-теорема
http://blog.nahurst.com/visual-guide-to-nosql-systems
ЧТО ТАКОЕ APACHE CASSANDRA?
История
Организация кластера
(consistent hashing), hinted handoff, read
repair
Структура данных
(SSTables), timestamps
?
Распределенная и горизонтально масштабируемая
http://techblog.netflix.com/2011/11/benchmarking-cassandra-scalability-on.html
Добавление новых нодов
• Скачать и распаковать дистрибутив
• Настроить IP
• Указать seed nodes
• Запустить
Что-то еще?
• Децентрализованная (кольцо, нет master node, нет single point of failure)
• Репликация между нодами и дата-центрами
• Настраиваемая Consistency (Tunable Consistency)
• Низкий уровень вхождения в NoSQL благодаря CQL (Cassandra Query Language)
• Поддержка Hadoop
И в чем подвох?
• Нет ACID транзакций
• Сложно гарантировать 100% consistency данных
• Нет сложных запросов (никаких like, join, group by)
• Схему данных приходится продумывать исходя из будущих запросов, а не наоборот
Когда имеет смысл использовать Apache Cassandra?
• Количество операций записи больше, чем чтения
• Данные должны быть постоянно доступны для чтения и записи, несмотря на потерю N нодов
• Анализ поведения пользователя
• Агрегаторы
• Мониторинг
Когда не нужна C*?
• Данные помещаются в память
• Данные помещаются на одном сервере
• Не предвидится серьезного роста объема данных
• Данные редко модифицируется и возможно реализовать шардинг
КАК APACHE CASSANDRA УСТРОЕНА ИЗНУТРИ?
Организация кластера
Запись в любой доступный нод кластера
Hinted Handoff
Read repair
Anti-entropy repair
• Что будет, если Coordinator Node умрет?
• Лучше запускать по расписанию
• bin/nodetool repair
Физическая организация данных
• Нет B-Trees
• Используются отсортированные в памяти таблицы фиксированного размера (SSTables)
• SSTable последовательно записываются на диск, а потом объеденяются в отдельном потоке (compaction)
• При удалении физически ничего не меняется, а ставится маркер (tombstone)
Физическая организация данных
ЛОГИЧЕСКАЯ СТРУКТУРА ДАННЫХ
= Map<Key, Map<Column, Value>>
Map<Key, Map<Column, Value>>
При использовании CQL все очень похоже на RDBMS
CREATE TABLE order_events (
order_id ascii,
operation_time timestamp,
operation_type ascii,
waiter ascii,
changed_menu_items list<ascii>,
PRIMARY KEY (order_id, operation_time)
);
Но в действительности все немного не так...
Идемпотентность
• Повторная запись по тому же ключу c теми же значениями ничего не меняет
• Insert == Update
INSERT INTO NerdMovies (movie, director, main_actor, year)
VALUES ('Serenity', 'Joss Whedon', 'Nathan Fillion', 2005);
UPDATE NerdMovies
SET director = 'Joss Whedon',
main_actor = 'Nathan Fillion',
year = 2005
WHERE movie = 'Serenity';
Распределенные счетчики
• Работают с той же скоростью, что и обычный update
• Не идемпотентны
UPDATE UserActions
SET total = total + 2
WHERE user = B70DE1D0-9908-4AE3-BE34-5573E5B09F14 AND action = 'click';
НЕСКОЛЬКО ПРИМЕРОВ...
Нагрузочное тестирование Black Box
Данные для каждой транзакции
CREATE TABLE transactions (
transaction_id ascii,
transaction_data map<text, text>,
PRIMARY KEY (transaction_id)
);
Данные для каждой транзакции
CREATE TABLE transaction_metrics (
transaction_id ascii,
tr_type ascii,
time timestamp,
PRIMARY KEY (transaction_id, tr_type)
);
Статистика
CREATE TABLE transaction_count (
stat_id ascii,
time_string ascii,
ops_count counter,
PRIMARY KEY (detail_key, time_string)
)
А теперь получаем нужный нам промежуток
SELECT time_string, ops_count FROM transaction_count
WHERE stat_id = ‘B_REQ|20140510'
AND time > '2014051003' AND time <= '2014051015'
Что не стоит делать с C*?
• Пытаться создать очередь на ее основе
• Читать перед записью – в большинстве случаев можно воспользоваться счетчиками или идемпотентностью
• Писать все в один Wide Row или часто удалять данные из него
НЮАНСЫ
Очень высокая загрузка CPU
• Слишком большой HEAP
• concurrent_reads/concurrent_writes
• native_transport_max_threads
• rpc_max_threads
Anti Entropy Repair
• nodetool repair
• Осбенно нужен в тех случаях, когда кластер оказался перегружен
Amazon EBS volumes
Слишком Wide Rows
• Запись в Wide Row оказалась в 5 раз медленне, чем в row с разными ключами
• Удаления из Wide Row требуют много памяти во время compaction (TombstoneOverwhelmingException)
• Все записи из Wide Row физически находятся на одном ноде (и его репликах)
Синхронизация времени между нодами
• Время на нодах (даже в AWS) может быть рассинхронизированно
• Timestamps оказываются неверными
• Данные в итоге тоже
Bugs
Баги есть!
...но правят их быстро
Администрирование
• Nodetool – command-line утилита, в которой есть все (или почти все) для администрирования кластера
• DataStax OpsCenter – красивый веб-интерфейс для администрирования, есть Community Edition
Правильный выбор технологий
VS
Q & A