aleksey yeschenko "Моделирование данных с помощью cql3"....

46
@AYeschenko Aleksey Yeschenko Apache Cassandra Committer, Engineer @DataStax Моделирование данных с CQL3: типичные паттерны и анти - паттерны

Upload: it-people

Post on 22-Jun-2015

935 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

@AYeschenko

Aleksey YeschenkoApache Cassandra Committer, Engineer @DataStax

Моделирование данных с CQL3: типичные паттерны и анти-паттерны

Page 2: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Кто я такой• Backend Ruby web-dev (давно и неправда) • Telecom Erlang dev (недавно и правда) •Принуждают использовать Java+Python (cqlsh) в DataStax с июля 2012 • Apache Cassandra committer с ноября 2012 •@AYeschenko

Page 3: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Когда использовать C*•Необходима Active-Active репликация между несколькими дата-центрами •Необходим (около) 100% аптайм •Данные больше не умещаются в PostgreSQL/MySQL/etc. • PostgreSQL/MySQL/etc. больше не справляются с объёмом записи •Модель Cassandra изначально идеально подходит для приложения •Нет необходимости в ad-hoc запросах •Любое другое решение стоит $$$$$

* 1 и более пунктов из списка == true

Page 4: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Когда не использовать C*• Во всех остальных случаях

Page 5: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Как использовать, если использовать

Page 6: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Корни С*

Dynamo

BigTable

• http://www.allthingsdistributed.com/2007/10/amazons_dynamo.html • http://research.google.com/archive/bigtable.html

Page 7: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Как хранятся данные + терминология

Имя ячейки ... Имя ячейки

Значение ячейки Значение ячейки

Timestamp Timestamp

TTL TTL

Partition ключ

1 2 Миллиарда

• Partition ключ и множество ячеек (до 2 миллиардов) • Хэш partition ключа определяет ноды, к которым принадлежит partition • Быстрое чтение по partition ключу •На диске и в памяти, ячейки всегда отсортированы по имени • Компаратор для сортировки задаётся пользователем

Page 8: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Идеальная нагрузка• Запись доминирует •Перезапись/удаление ячеек отсутствуют или не очень часты • Чтение по ключу + (имени ячейки или небольшим отрезкам ячеек в порядке компаратора)

Page 9: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Идеальная нагрузка•Логи •Данные с сенсоров • Финансовые данные (ticks) • Ads - клики и отображения, аналитика •Необязательно именно временные ряды (в порядке timestamp); любые данные, естественно упорядоченные по последовательному значению •Нужны последние N значений

Page 10: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Паттерн #1: временной ряд

Page 11: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

CREATE TABLE temperature (

weatherstation_id text,

event_time timestamp,

temp int,

PRIMARY KEY (weatherstation_id, event_time)

) WITH CLUSTERING ORDER BY (event_time DESC);

partition ключ

кластеринговая колонка

составной ключобратный порядок сортировки ячеек

• Каждая станция регулярно собирает показания •Один partition == одна станция •Одно показание == одна ячейка (здесь две, технически) •Потенциально очень широкий partition

Паттерн #1: временной ряд

Page 12: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

CREATE TABLE temperature (

weatherstation_id text,

event_time timestamp,

temp int,

PRIMARY KEY (weatherstation_id, event_time)

) WITH CLUSTERING ORDER BY (event_time DESC);

partition ключ

кластеринговая колонка

составной ключобратный порядок сортировки ячеек

1386475781 1386475781:temp 1386475780 1386475780:temp 1386475779 1386475779:temp …

* -6 * -6 * -5 …SVO

weatherstation_id event_time temp * маркеры CQL3 ряда

Паттерн #1: временной ряд

Page 13: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

CREATE TABLE temperature (

weatherstation_id text,

date text,

event_time timestamp,

temp int,

PRIMARY KEY ((weatherstation_id, date), event_time)

) WITH COMPACT STORAGE AND CLUSTERING ORDER BY (event_time DESC);

составной partition ключ

•Один partition для пары {weatherstation_id, date} •Отсутствие оверхеда маркера ряда и имени колонки

Паттерн #1: временной ряд

Page 14: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

CREATE TABLE temperature (

weatherstation_id text,

date text,

event_time timestamp,

temp int,

PRIMARY KEY ((weatherstation_id, date), event_time)

) WITH COMPACT STORAGE AND CLUSTERING ORDER BY (event_time DESC);

1386475781 1386475780 1386475779 …

-6 -6 -5 …SVO:2013-12-09

weatherstation_iddate

timestamp temp

составной partition ключ

Паттерн #1: временной ряд

Page 15: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #1: неуместное использование встроенных индексов• RDBMS опыт с индексацией НЕ переносится в C*

Page 16: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #1: неуместное использование встроенных индексов• RDBMS опыт с индексацией НЕ переносится в C* • Встроенные индексы в C* != RDBMS индексы

Page 17: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #1: неуместное использование встроенных индексов• RDBMS опыт с индексацией НЕ переносится в C* • Встроенные индексы в C* != RDBMS индексы • Встроенные индексы в C* != RDBMS индексы

Page 18: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #1: неуместное использование встроенных индексов• RDBMS опыт с индексацией НЕ переносится в C* • Встроенные индексы в C* != RDBMS индексы • Встроенные индексы в C* != RDBMS индексы • Встроенные индексы в C* != RDBMS индексы

Page 19: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #1: неуместное использование встроенных индексов• RDBMS опыт с индексацией НЕ переносится в C* • Встроенные индексы в C* != RDBMS индексы • Встроенные индексы в C* != RDBMS индексы • Встроенные индексы в C* != RDBMS индексы •Для удобства, не для улучшения производительности •Достаточно ограничены в плане удобства • Следует избегать, по большей части

Page 20: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

cqlsh:nope> CREATE TABLE users (

... username varchar,

... email varchar,

... fullname varchar,

... last_login timestamp,

... PRIMARY KEY (username)

... );

!

cqlsh:nope> INSERT INTO users (username, email, fullname) VALUES ('ay', '[email protected]', 'Aleksey Yeschenko');

!

cqlsh:nope> SELECT * FROM users WHERE email = '[email protected]';

Bad Request: No indexed columns present in by-columns clause with Equal operator

Анти-паттерн #1: неуместное использование встроенных индексов

Page 21: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #1: неуместное использование встроенных индексов

Page 22: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

cqlsh:nope> CREATE INDEX ON users (email);

!

cqlsh:nope> SELECT * FROM users WHERE email = '[email protected]';

username | email | fullname | last_login

----------+----------------------+-------------------+------------

ay | [email protected] | Aleksey Yeschenko | null

!

(1 rows)

Анти-паттерн #1: неуместное использование встроенных индексов

Page 23: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #1: неуместное использование встроенных индексов•При высокой и средней кардинальности колонки решается ‘ручным’ вторичным индексом •Отдельная таблица для обратного лукапа

Page 24: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

cqlsh:yep> CREATE TABLE users (

... username varchar,

... email varchar,

... fullname varchar,

... last_login timestamp,

... PRIMARY KEY (username)

... );

cqlsh:yep> CREATE TABLE users_by_email_idx (

... email varchar,

... username varchar,

... PRIMARY KEY (email, username)

... );

Анти-паттерн #1: неуместное использование встроенных индексов

Page 25: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

cqlsh:yep> BEGIN BATCH

... INSERT INTO users (username, email, fullname) VALUES ('ay', '[email protected]', 'Aleksey Yeschenko');

... INSERT INTO users_by_email_idx (email, username) VALUES ('[email protected]', 'ay');

... APPLY BATCH;

!cqlsh:yep> SELECT username FROM users_by_email_idx WHERE email = '[email protected]';

username

----------

ay

!cqlsh:yep> SELECT * FROM users WHERE username = 'ay';

username | email | fullname | last_login

----------+----------------------+-------------------+------------

ay | [email protected] | Aleksey Yeschenko | null

Анти-паттерн #1: неуместное использование встроенных индексов

Page 26: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

•При средней/низкой кардинальности свой, отдельный набор проблем • Главная - большое количество random i/o • Решается правильной моделью/денормализацией вместо использования встроенных индексов

Анти-паттерн #1: неуместное использование встроенных индексов

Page 27: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

•Q: Когда вообще следует использовать встроенные индексы? • A: Для поиска рядов с 1+ кластеринговыми колонками внутри определённого partition (зная partition ключ)

Анти-паттерн #1: неуместное использование встроенных индексов

Page 28: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #1: неуместное использование встроенных индексовCREATE TABLE example (

partition_key varchar,

clustering_col0 varchar,

clustering_col1 varchar,

val varchar

);

!

CREATE INDEX ON example (val);

!

SELECT * FROM example WHERE partition_key = ‘some_pk’ AND val = ‘some_val’;

Анти-паттерн #1: неуместное использование встроенных индексов

Page 29: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #1: неуместное использование встроенных индексовАнти-паттерн #1: неуместное использование встроенных индексов• Всё вышесказанное распространяется на индексы коллекций в 2.1 •Обращайтесь со встроенными индексами как с expert-level feature

Page 30: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Паттерн #2: денормализация

username firstname lastname email

tcodd Edgar Codd [email protected] Raymond Boyce [email protected]

videoid videoname username description tags99051fe9 My funny cat tcodd My cat plays

the pianocats,piano,lol

b3a76c6b Math tcodd Now my dog plays

dogs,piano,lol

Users

Videos

•Отношения без реляционности • Без использования foreign key • Users 1-M Videos

CREATE TABLE videos (! videoid uuid,! videoname varchar,! username varchar,! description varchar, ! tags varchar,! upload_date timestamp,! PRIMARY KEY(videoid)!);

CREATE TABLE users (! username varchar,! firstname varchar,! lastname varchar,! email varchar, ! PRIMARY KEY(username)!);

Page 31: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Паттерн #2: денормализация

CREATE TABLE username_video_index (! username varchar,! videoid uuid,! upload_date timestamp,! video_name varchar,! PRIMARY KEY (username, videoid)!);

SELECT video_name!FROM username_video_index!WHERE username = ‘ctodd’!AND videoid = ‘99051fe9’

•Лукап видео по username • Запись в две таблицы сразу • Без встроенных индексов

Page 32: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Паттерн #2: денормализация

username videoid commenttcodd 99051fe9 Sweet!rboyce b3a76c6b Boring :(

• Users 1-M Comments • Videos 1-M Comments • Без встроенных индексов

username firstname lastname email

tcodd Edgar Codd [email protected] Raymond Boyce [email protected]

videoid videoname username description tags99051fe9 My funny cat tcodd My cat plays

the pianocats,piano,lol

b3a76c6b Math tcodd Now my dog plays

dogs,piano,lol

Users

Videos

Comments

Page 33: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Паттерн #2: денормализация

CREATE TABLE comments_by_video (! videoid uuid,! username varchar,! comment_ts timestamp,! comment varchar,! PRIMARY KEY (videoid,username)!);

CREATE TABLE comments_by_user (! username varchar,! videoid uuid,! comment_ts timestamp,! comment varchar,! PRIMARY KEY (username,videoid)!);

•Две таблицы для выборки по видео и по пользователям • Запись в три таблицы сразу (comments, comments_by_video, comments_by_user) •Не жалеть запись

Page 34: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #2: очереди и очереде-подобные нагрузки

Page 35: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #2: очереди и очереде-подобные нагрузки• Cassandra не лучшее решение для очередей •Можно, но требует гимнастики •Лучше использовать что-нибудь вроде Kafka/RabbitMQ •Любой паттерн, где в partition удаляются ячейки и выполняются slice сканы, включающие удалённые ячейки •Пример - нарочно упрощён, ради иллюстрации

Page 36: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #2: очереди и очереде-подобные нагрузки—— naive путь

CREATE TABLE queues (

name text,

enqueued_at timeuuid,

payload blob,

PRIMARY KEY (name, enqueued_at) —— ячейки упорядочены по времени вставки, ASC

) WITH COMPACT STORAGE;

Page 37: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #2: очереди и очереде-подобные нагрузки—— 1000x добавить в очередь:

INSERT INTO queues (name, enqueued_at, payload) VALUES (‘queue-1’, now(), 0x…);

!

—— 999x убрать из очереди, индивидуально:

DELETE FROM queues WHERE name = ‘queue-1’ AND enqueued_at = ?;

!

—— достать последний элемент из очереди:

SELECT enqueued_at, payload

FROM queues

WHERE name = 'queue-1'

LIMIT 1;

Page 38: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #2: очереди и очереде-подобные нагрузки

51c220e0-60… 58940a00-60.. 61163b30-60.. 995 x … 6e1ac030-60… ab36fa10-60..

X X X X X <some blob>queue-1

Page 39: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #2: очереди и очереде-подобные нагрузкиactivity | source | elapsed

-------------------------------------------+-----------+--------

execute_cql3_query | 127.0.0.3 | 0

Message received from /127.0.0.3 | 127.0.0.1 | 42

Sending message to /127.0.0.1 | 127.0.0.3 | 718

Executing single-partition query on queues | 127.0.0.1 | 145

Acquiring sstable references | 127.0.0.1 | 158

Merging memtable contents | 127.0.0.1 | 189

Merging data from memtables and 0 sstables | 127.0.0.1 | 235

Read 1 live and 9999 tombstoned cells | 127.0.0.1 | 251102

Enqueuing response to /127.0.0.3 | 127.0.0.1 | 252976

Sending message to /127.0.0.3 | 127.0.0.1 | 253052

Message received from /127.0.0.1 | 127.0.0.3 | 324314

Processing response from /127.0.0.1 | 127.0.0.3 | 324535

Request complete | 127.0.0.3 | 324812

Page 40: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #2: очереди и очереде-подобные нагрузки• partition сканируется до тех пор пока LIMIT неудалённых ячеек не будет собран, или • пока не закончились ячейки в partition, или • пока не встретится ячейка вне заданных границ (если указано в where)

Page 41: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #2: очереди и очереде-подобные нагрузки—— зная последний удалённый элемент

SELECT enqueued_at, payload

FROM queues

WHERE name = 'queue-1'

AND enqueued_at > 6e1ac030-60b9-11e3-949a-0800200c9a66

LIMIT 1;

Page 42: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #2: очереди и очереде-подобные нагрузки

51c220e0-60… 58940a00-60.. 61163b30-60.. 995 x … 6e1ac030-60… ab36fa10-60..

X X X X X <some blob>queue-1

Page 43: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #2: очереди и очереде-подобные нагрузкиactivity | source | elapsed

-------------------------------------------+-----------+--------

execute_cql3_query | 127.0.0.3 | 0

Sending message to /127.0.0.1 | 127.0.0.3 | 965

Message received from /127.0.0.3 | 127.0.0.1 | 34

Executing single-partition query on queues | 127.0.0.1 | 339

Acquiring sstable references | 127.0.0.1 | 355

Merging memtable contents | 127.0.0.1 | 461

Partition index lookup over for sstable 3 | 127.0.0.1 | 1122

Merging data from memtables and 1 sstables | 127.0.0.1 | 2268

Read 1 live and 0 tombstoned cells | 127.0.0.1 | 4404

Message received from /127.0.0.1 | 127.0.0.3 | 6109

Enqueuing response to /127.0.0.3 | 127.0.0.1 | 4492

Sending message to /127.0.0.3 | 127.0.0.1 | 4606

Processing response from /127.0.0.1 | 127.0.0.3 | 6608

Request complete | 127.0.0.3 | 6901

Page 44: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Анти-паттерн #2: очереди и очереде-подобные нагрузки• partitioning по дате • хинты для чтения • то же относится к TTL • худший сценарий - death by OOM • https://issues.apache.org/jira/browse/CASSANDRA-6117 (Avoid death-by-tombstone by default) 10k warning, 50k error • http://www.datastax.com/dev/blog/cassandra-anti-patterns-queues-and-queue-like-datasets

Page 45: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Что дальше - вебинары по моделированию• http://youtu.be/px6U2n74q3g - The Data Model is Dead, Long Live the Data Model • http://youtu.be/qphhxujn5Es - Become a Super Modeler • http://youtu.be/T_WRC_GjRd0 - The World's Next Top Data Model • http://youtu.be/UP74jC1kM3w - Understanding How CQL3 Maps to Cassandra's Internal Data Structure

Page 46: Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassandra Conf 2013

Вопросы?