2. Elevator Pitch (40 слов)
Apache Cassandra – открытая,
распределенная, децентрализованная,
эластично масштабируемая,
высокодоступная, отказоустойчивая,
строковая, допускающая настройку
согласованности СУБД, дизайн
распределенности которой основан на
Amazon Dynamo, а модель данных – на
Google BigTable. Разработана в Facebook,
ныне используется на некоторых из
наиболее популярных веб-сайтов.
Poliakov Andrei: 2018 2
3. Основная информация
Apache Cassandra
Первый выпуск 2008
Написана на Java
Разработчик Изначально Facebook, затем передана в Apache Software
Foundation (компания DataStax)
Используется в Constant Contact, CERN, Comcast, eBay,GitHub, GoDaddy, Hulu, I
nstagram, Intuit, Netflix, Reddit, The Weather Channel, and over
1500 more companies that have large, active data sets.
Последняя версия 3.11.3 (31 июля 2018)
Сайт cassandra.apache.org
Poliakov Andrei: 2018 3
5. Для кого подходит Cassandra?
• Крупное развертывание
• Много операций записи, статистика, анализ
• Территориальная разнесенность
• Быстро эволюционирующие приложения
Poliakov Andrei: 2018 5
6. Что взяли из Dynamo?
• Token ring
• Алгоритм записи/чтения
Poliakov Andrei: 2018 6
7. Что взяли из BigTable?
• Модель данных key/column
• Локальную структуру данных на серверах
• Memtable/commit log – временное хранилище
• SSTable/Bloomfilter – постоянное хранилище
• Вместо put/get доступны сложные запросы:
SELECT WHERE key >= start AND key <= end AND columnName >= c1
AND columnName <= c2
• Индексы
Poliakov Andrei: 2018 7
9. Модель данных Cassandra
Таблица
Строка
Первичный ключ
Столбец 1
Значение 1
Столбец 2
Значение 2
Столбец 3
Значение 3
Строка
Первичный ключ
Столбец 1
Значение 1
Столбец 4
Значение 4
Poliakov Andrei: 2018 9
10. Таблица
Широкая строка
Широкая строка в cassandra
Ключ
раздела
Статический
столбец
Значение
Кластерный
ключ
Значение
Столбец
Значение
Кластерный
ключ
Значение
Столбец
Значение
Широкая строка
Ключ
раздела
Статический
столбец
Значение
Кластерный
ключ
Значение
Столбец
Значение
Столбец
Значение
Poliakov Andrei: 2018 10
12. Запись
• Команда идет на произвольный сервер в кластере. Сервер
находит нужные реплики (ReplicationStrategy)
• Сервер сохраняет данные локально (Hinted handoff)
• Критерий успешности записи определяет клиент согласно
настройки ConsistencyLevel
Уровень Что значит
ANY Начальный сервер (Hinted Handoff)
ONE Хотя бы одна реплика
QUORUM (ReplicationFactor / 2) + 1
ALL Все реплики
Poliakov Andrei: 2018 12
13. Хранение данных
Узел Cassandra
Демон Cassandra (JVM)
Таблицы в памяти Кэши ключей Кэши строк
Диск
Журналы фиксаций Файлы SSTable Напоминания (2.2+)
Poliakov Andrei: 2018 13
14. Запись: внутренности
• Memtable: хранилище новых записей. Настраиваемый flush-
критерий (по таймауту, по размеру)
• Commit-log: дублирует memtable на случай падения сервера.
• Memtable flush -> SSTable
• SSTable: data + index + bloomfilter
• SSTable compaction – борьба с фрагментацией
Poliakov Andrei: 2018 14
15. Чтение
• Команду на чтение обрабатывает произвольный сервер
• Сервер определяет ближайшую реплику на основе настройки
snitch: Simple, Topology, Dynamic
• Клиент определяет критерий успешности чтения
• Read repair (optional): убедиться, что все реплики содержат
свежие данные
Уровень Что значит
ONE Хотя бы одна реплика
QUORUM (ReplicationFactor / 2) + 1
ALL Все реплики
Poliakov Andrei: 2018 15
16. Конфликты
• Каждое значение в колонке имеет timestamp
• Timestamp поставляется клиентом как текущее время
• Можно переопределить timestamp на любое 64-х битное число
• Клиент получает всегда последний timestamp
Poliakov Andrei: 2018 16
17. Кэширование запросов
• Key cache: кеширование позиции ключей внутри SSTable
• Row cache: кеширование ключей и их значений в памяти
• Принцип кеширования: LIFO. Настраивается для каждой таблицы
отдельно.
• Настройки кеширования использовать не рекомендуется. Лучше
полагаться на кеширование файловой системы (в ОС есть mmap
кэш, который использует Cassandra).
Poliakov Andrei: 2018 17
18. Индексы
• Secondary indexes: на columns:
CREATE INDEX <name> ON <table_name(<column_name>)
• При полностью распределенной архитектуре сложно реализовать
индексы
• Чтобы найти значение по индексу, нужно опросить все сервера
• Ограничение реализации: можно делать запросы только по
строгому сравнению* (SELECT … WHERE column >value – не
поддерживается)
• Индексы сильно замедляют вставку данных
• Итого: индексы довольно бесполезная фича
* SASI индексы (разработаны Apple) включенные в Cassandra 3.4 поддерживают сравнение на
больше/меньше и LIKE. SASI хранятся как часть каждого файла SSTable, а не в отдельной «скрытой»
таблице как оригинальные индексы Cassandra. Poliakov Andrei: 2018 18
21. Пользовательские типы
1. CREATE TYPE address (
... street text,
... city text,
... state text,
... zip_code int);
2. ALTER TABLE user ADD addresses map<text,
frozen<address>>;
3. UPDATE user SET adresses = adresses + {'home' : {street:
'Lenina street', city: 'Chelyabinsk', state: 'Chelyabinsk oblast',
zip_code: 454130}} WHERE first_name = 'Bill';
2. ALTER TABLE user ADD addresses map<text, address>;
Poliakov Andrei: 2018 21
22. TTL (время жизни столбца) и временные метки
• Возможность задать срок хранения данных, необходимость в которых
отпала (работает на уровне значений отдельных столбцов).
UPDATE user USING TTL 3600 SET last_name = ‘McDonald’ WHERE
fisrt_name = ‘Robin’;
SELECT first_name, last_name, TTL(last_name) FROM user;
• Всякий раз, как мы записываем данные, Cassandra генерирует
временную метку для каждого обновленного столбца (в общем случае
сохраняется изменение с самой поздней временной меткой)
SELECT writetime(first_name) FROM user;
SELECT writetime(second_name) FROM user;
Poliakov Andrei: 2018 22
24. Создание и настройка кластера (практика)
• На примере ccm:
• Создание кластера
• Добавление узлов и пересчет токенов
• Динамическое добавление узлов (выход узлов из строя и
возвращение в кластер)
Poliakov Andrei: 2018 24
26. Легковесные транзакции (LWT)
• Традиционный подход: распределенные транзакции и
двухфазная фиксация.
• Что делать, когда строгой согласованности мало для
предотвращения состояния гонки в случаях, когда клиент должен
сначала прочитать, а затем записать данные? Нужна
линеаризуемая согласованность (в терминах ACID –
последовательный уровень изоляции).
Poliakov Andrei: 2018 26
28. Легковесные транзакции (LWT)
• Расширяем Paxos:
для успешного завершения
транзакции необходимы четыре
раунда коммуникации между
координатором и репликами.
1) подготовка/обещание
2) чтение/результаты
3) предложение/принятие
4) фиксация/подтверждение
Poliakov Andrei: 2018 28
29. Легковесные транзакции (LWT)
• Пример 1: регистрируем пользователя
INSERT INTO USERS (login, email, name, login_count)
values ('jbellis', 'jbellis@datastax.com', 'Jonathan Ellis', 1)
IF NOT EXISTS
• Пример 2: сбрасываем пароль:
UPDATE users
SET reset_token = null, password = 'newpassword'
WHERE login = 'jbellis'
IF reset_token = 'some-generated-reset-token'
Poliakov Andrei: 2018 29
30. Материализованные представления
CREATE MATERIALIZED VIEW <view_name>
AS SELECT *
FROM <base_table_name>
WHERE k1 IS NOT NULL AND … kn IS NOT NULL
AND custom_column IS NOT NULL
PRIMARY KEY (custom_column, k1, …, kn);
Poliakov Andrei: 2018 30
31. Масштабирование: как добавить сервера в
кластер?
• У каждого сервера есть операция move token. Можно
переназначить token у любого сервера
• Топология кластера изменится, миграция данных будет
происходить в фоне
• Пока миграция не закончена, сервер будет отвечать за старый
кусок данных
• Аналогично будет отработана ситуация добавления нового
сервера в token ring
Poliakov Andrei: 2018 31
32. Стратегии репликации
• Первая реплика всегда хранится в узле, которому принадлежит
диапазон, куда попал маркер, а местоположение остальных
реплик определяется стратегией репликации:
• AbstractReplicationStrategy
• SimpleStrategy
• TopologyStrategy
• OldNetworkTopologyStrategy
Poliakov Andrei: 2018 32
33. Многоступенчатая событийно-
ориентированная архитектура (SEDA)
• Операция может начаться в одном потоке, затем продолжиться в другом,
который может передать работу другому потоку.
• Работа разбивается на ступени (stage) и ход выполнения определяет пул
потоков (java,util.concurrent.ExecutorService), ассоциированный со ступенью.
• Ступень состоит из входящей очереди событий, обработчика событий и
ассоциированного пула потоков. Ступени управляются контроллером,
который отвечает за планирование и выделение потоков.
Примеры:
• Чтение (локальное чтение)
• Изменение (локальная запись)
• Исправления на этапе чтения
• Миграция (внесение изменений в схему)
• Вручение напоминаний
Poliakov Andrei: 2018 33
34. Преимущества
• Быстрый write, особенно когда не нужна consistency.
• Легкость в администрировании. Один демон (daemon) с одним
конфигурационным файлом.
• Распределенность, устойчивость к разрывам сети
• Высокая доступность
Poliakov Andrei: 2018 34
35. Недостатки
• Плохо реализован range scan: кассандра не умеет передавать
данные поточно.
• Слишком много настроек вынесено на cluster level: вид и
стратегия хранения ключей и т.д.
• В старых версиях: протокол общения между нодами Thrift
Poliakov Andrei: 2018 35
37. Вопрос 1: Выберите верные утверждения
В Cassandra нет схемы данных
Cassandra поддерживает гибкую схему данных
API, основанный на Thrift является рекомендуемым
Рекомендуется использовать CQL
Poliakov Andrei: 2018 37
38. Вопрос 1: Выберите верные утверждения
В Cassandra нет схемы данных
Cassandra поддерживает гибкую схему данных
API, основанный на Thrift является рекомендуемым
Рекомендуется использовать CQL
Poliakov Andrei: 2018 38
39. Вопрос 2: Что будет выведено в результате
запроса ”SELECT * FROM user WHERE
second_name = ‘Gates’“?
Таблица создана запросом: CREATE TABLE user (first_name text, second_name
text, PRIMARY KEY (first_name));
В таблицу вставлены данные: {Bill Gates, Steve Jobs}
ofirst_name | second_name
------------+-------------
Bill | Gates
oБудет ошибка, т.к. не созданы вторичные индексы
ofirst_name | second_name
------------+-------------
oБудет ошибка, т.к. не создано материализованное представление
Poliakov Andrei: 2018 39
40. Вопрос 2: Что будет выведено в результате
запроса ”SELECT * FROM user WHERE
second_name = ‘Gates’“?
Таблица создана запросом: CREATE TABLE user (first_name text, second_name
text, PRIMARY KEY (first_name));
В таблицу вставлены данные: {Bill Gates, Steve Jobs}
ofirst_name | second_name
------------+-------------
Bill | Gates
oБудет ошибка, т.к. не созданы вторичные индексы
ofirst_name | second_name
------------+-------------
oБудет ошибка, т.к. не создано материализованное представление
Poliakov Andrei: 2018 40
41. Вопрос 3: Какой уровень согласованности
данных поддерживается в Cassandra?
oСлабая согласованность (в конечном счете)
oНастраиваемый уровень согласованности
oСтрогая согласованность
oПричинно-следственная согласованность
Poliakov Andrei: 2018 41
42. Вопрос 3: Какой уровень согласованности
данных используется в Cassandra?
oСлабая согласованность (в конечном счете)
oНастраиваемый уровень согласованности
oСтрогая согласованность
oПричинно-следственная согласованность
Poliakov Andrei: 2018 42
43. Вопрос 4: Согласованность «в конечном
счете» означает:
oВсе обновления рано или поздно распространятся во все реплики
и реплики станут согласованными
oПоследовательная согласованность
oСтрогая согласованность
oСогласованным считается самое последнее записанное значение
Poliakov Andrei: 2018 43
44. Вопрос 4: Согласованность «в конечном
счете» означает:
oВсе обновления рано или поздно распространятся во все реплики
и реплики станут согласованными
oПоследовательная согласованность
oСтрогая согласованность
oСогласованным считается самое последнее записанное значение
Poliakov Andrei: 2018 44
45. Вопрос 5: Как создать вторичный индекс?
oCREATE INDEX <name> ON table_name(column_name);
oCREATE CUSTOM INDEX <name> ON table_name(column_name);
oCREATE SECONDARY INDEX <name> ON table_name(column_name);
oCREATE CUSTOM INDEX <name> ON table_name(column_name)
USING ‘org.apache.Cassandra.index.sasi.SASIIndex’;
Poliakov Andrei: 2018 45
46. Вопрос 5: Как создать вторичный индекс?
oCREATE INDEX <name> ON table_name(column_name);
oCREATE CUSTOM INDEX <name> ON table_name(column_name);
oCREATE SECONDARY INDEX <name> ON table_name(column_name);
oCREATE CUSTOM INDEX <name> ON table_name(column_name)
USING ‘org.apache.Cassandra.index.sasi.SASIIndex’;
Poliakov Andrei: 2018 46
47. Вопрос 6: Имеется пользовательский тип
address. Что произойдет при попытке добавить
колонку в таблицу: ALTER TABLE user ADD
addresses map<text, address>;
Таблица создана запросом: CREATE TABLE user (first_name text,
second_name text, PRIMARY KEY (first_name));
oКолонка будет успешно добавлена в таблицу
oБудет ошибка, т.к. вложенная коллекция (пользовательский тип) не
заморожена
oБудет ошибка, т.к. вложенная коллекция (пользовательский тип)
заморожена
oБудет ошибка, т.к. не создано материализованное представление
для пользовательского типаPoliakov Andrei: 2018 47
48. Вопрос 6: Имеется пользовательский тип
address. Что произойдет при попытке добавить
колонку в таблицу: ALTER TABLE user ADD
addresses map<text, address>;
Таблица создана запросом: CREATE TABLE user (first_name text,
second_name text, PRIMARY KEY (first_name));
oКолонка будет успешно добавлена в таблицу
oБудет ошибка, т.к. вложенная коллекция (пользовательский тип) не
заморожена
oБудет ошибка, т.к. вложенная коллекция (пользовательский тип)
заморожена
oБудет ошибка, т.к. не создано материализованное представление
для пользовательского типаPoliakov Andrei: 2018 48
49. Вопрос 7: Какую согласованность мы получим,
если укажем при запросе уровень
согласованности равным коэффициенту
репликации?
oСтрогую
oВ конечном счете
oНикакую
oЖелезную
Poliakov Andrei: 2018 49
50. Вопрос 7: Какую согласованность мы получим,
если укажем при запросе уровень
согласованности равным коэффициенту
репликации?
oСтрогую
oВ конечном счете
oНикакую
oЖелезную
Poliakov Andrei: 2018 50
51. Вопрос 8: Какие ограничения накладываются на
материализованное представление?
oВ первичный ключ материализованного представления нельзя
включать несколько столбцов, не входящих в состав первичного
ключа базовой таблицы
oМатериализованные представления можно создавать только для
таблиц, не содержащих кластерные столбцы
oОграничения для материализованных представлений аналогичны
ограничениям при создании обычных таблиц
oНельзя использовать агрегаты
Poliakov Andrei: 2018 51
52. Вопрос 8: Какие ограничения накладываются на
материализованное представление?
oВ первичный ключ материализованного представления нельзя
включать несколько столбцов, не входящих в состав первичного
ключа базовой таблицы
oМатериализованные представления можно создавать только для
таблиц, не содержащих кластерные столбцы
oОграничения для материализованных представлений аналогичны
ограничениям при создании обычных таблиц
oНельзя использовать агрегаты
Poliakov Andrei: 2018 52
53. Вопрос 9: Коэффициент репликации
задается:
oОдин раз для каждой таблицы
oКлиентом в каждом запросе
oОдин раз для всего пространства ключей
oКлиентом в каждом запросе на обновление таблицы
Poliakov Andrei: 2018 53
54. Вопрос 9: Коэффициент репликации
задается:
oОдин раз для каждой таблицы
oКлиентом в каждом запросе
oОдин раз для всего пространства ключей
oКлиентом в каждом запросе на обновление таблицы
Poliakov Andrei: 2018 54
55. Вопрос 10: Почему Cassandra не стоит
использовать в качестве очереди:
Очередь схожа с паттерном временных рядов
Растущее число «надгробий» отрицательно сказывается на
производительности
Удаленные элементы не исчезают из таблицы и нужно
пропустить, чтобы добраться до начала очереди
Элементы очереди нельзя изменять
Poliakov Andrei: 2018 55
56. Вопрос 10: Почему Cassandra не стоит
использовать в качестве очереди:
Очередь схожа с паттерном временных рядов
Растущее число «надгробий» отрицательно сказывается на
производительности
Удаленные элементы не исчезают из таблицы и нужно
пропустить, чтобы добраться до начала очереди
Элементы очереди нельзя изменять
Poliakov Andrei: 2018 56
57. Вопрос 11: Что будет выведено по запросу
SELECT * FROM user WHERE first_name = 'Bill’; ?
Таблица создана запросом: CREATE TABLE user (first_name text, second_name
text, PRIMARY KEY (first_name));
В таблицу вставлены данные: {Bill Gates, Steve Jobs}
Выполнен запрос DELETE second_name FROM user WHERE first_name = ‘Bill’;
ofirst_name | second_name
------------+-------------
Bill | null
oБудет ошибка, т.к. не созданы вторичные индексы
ofirst_name | second_name
------------+-------------
ofirst_name |
------------|
Bill | Poliakov Andrei: 2018 57
58. Вопрос 11: Что будет выведено по запросу
SELECT * FROM user WHERE first_name = 'Bill’; ?
Таблица создана запросом: CREATE TABLE user (first_name text, second_name
text, PRIMARY KEY (first_name));
В таблицу вставлены данные: {Bill Gates, Steve Jobs}
Выполнен запрос DELETE second_name FROM user WHERE first_name = ‘Bill’;
ofirst_name | second_name
------------+-------------
Bill | null
oБудет ошибка, т.к. не созданы вторичные индексы
ofirst_name | second_name
------------+-------------
ofirst_name |
------------|
Bill | Poliakov Andrei: 2018 58
Editor's Notes
Стр. 67-68
Можно развернуть на одном узле, но возможно стоит использовать РСУБД (проще и более знакомая).Быстрее операции записи, чем операции чтения данных (Cassandra оптимизирована для записи: большое количество записей и параллельных клиентов).Возможны сценарии проведения репликации из одного ЦОДа в другие (выигрыш в производительности, если данные находятся рядом с пользователем).
Cassandra хорошо подходит для "молодых" приложений и стартапов, так как поддерживает гибкую схему данных.
Стр 93
Кластер – контейнер пространств ключей, расположенных в одном или нескольких узлах. Также называют кольцом, т.к. Cassandra распределяет данные между узлами кластера, считая их закольцованными.
Пространство ключей – контейнер таблиц.
Таблица – логическая структура, объединяющая похожие данные, контейнер строк.
Строка – контейнер столбцов, на который можно сослаться по первичному ключу. Строка состоит из первичного ключа (состоящего из одного или нескольких столбцов) и дополнительных столбцов.
Столбец – пара «имя-значение»
Стр 94
Широкие строки – строки, содержащие много столбцов (также называются разделами).
В широких строках используется составной первичный ключ. Составной ключ состоит из ключа раздела (partition key) и необязательных кластерных столбцов (clustering column). Ключ раздела служит для определения узлов, на которых хранятся строки. Кластерные столбцы используются для управления сортировкой данных при хранении внутри раздела.
Статические столбцы служат для хранения данных, которые не являются частью первичного ключа, но одинаковы во всех строках одного раздела.
Виртуальные узлы (v-узлы) – вместо того, чтобы назначать узлу один маркер, диапазон маркеров разбивается на несколько меньших диапазонов. Затем каждому физическому узлу назначается несколько маркеров. По умолчанию каждому узлу назначается 256 таких маркеров, т.е. он содержит 256 виртуальных узлов. Виртуальные узлы по умолчанию включены. Виртуальные узлы ускоряют тяжелые операции: инициализация нового узла, вывод узла из эксплуатации и исправление узла. Связано это с тем, что нагрузка, ассоциированная с операциями в нескольких меньших диапазонах, более равномерно распределяется между узлами кластера.
Разделители: Murmur3Partitioner, RandomPartitioner.
Hinted handoff – вручение напоминаний
QUORUN и ALL – строгие уровни согласованности
ANY, ONE, TWO, THREE - слабые
CREATE CUSTOM INDEX <name> ON table_name(column_name) USING ‘org.apache.Cassandra.index.sasi.SASIIndex’;
Пример работы с Cassandra с помощью CQL(показать работу с CQL в консоли)
Первичный ключ материализованного представления должен включать все столбцы первичного ключа базовой таблицы. Это ограничение не позволяет Cassandra свернуть несколько строк базовой таблицы в одну строку материализованного представления, что сильно бы усложнило бы управление обновлениями.
Чаще всего вначале помещают дополнительный столбец, который становится ключом раздела, а за ним – столбцы, входящие в состав первичного ключа базовой таблицы, которые в материализованном представлении оказываются кластерными столбцами.
Фильтр необходимо задать для каждого столбца первичного ключа материализованного представления (например, IS NOT NULL).
SimpleStrategy – помещает реплики в соседние узлы кольца, начиная с узла, указанного разделителем
TopologyStrategy – позволяет задать различные коэффициенты репликации для каждого ЦОДа. В пределах одного ЦОДа он распределяет реплики по разным стойкам, стремясь максимизировать доступность.
OldNetworkTopologyStrategy – оставлена ради обратной совместимости