Download - Класс!ная Cassandra

Transcript
Page 1: Класс!ная Cassandra

Олег Анастасьевведущий разработчик,Одноклассники

Класс!ная Cassandra

Page 2: Класс!ная Cassandra

> 6 M онлайн

290 000 страниц/сек, 20 ms на страницу

>240 Гбит/сек

> 5 000 серверов в 4 ЦОД99.9% java

Page 3: Класс!ная Cassandra

=NoSQL

ВысокодоступнаяРаспределенная

Система Управления Даннымис Открытым Кодом

Page 4: Класс!ная Cassandra

Оценки фото

Класс!

Архив сообщений

... и много других

Cassandra @

Page 5: Класс!ная Cassandra

Введение в Cassandra( сильно упрощенное )

Page 6: Класс!ная Cassandra

Cassandra

Data Range

00-64

- Кластер, gossip- Партиционирование по ключу- Высокая доступность- Поддержка нескольких ЦОД

- Масштабирование,восстановление на ходу

- Не нужны бакапы

0

64

128

192

R1R3

R2

Строки токен(к)

0-63

Строки токен(к)

64-127

Строки токен(к)

128-191

Строки токен(к)

192-...

Page 7: Класс!ная Cassandra

Запись в кластер

192

HintStorage

THRIFT

Изменение

0

64

128

Page 8: Класс!ная Cassandra

Запись в кластер

192

HintStorage

THRIFT

Изменение

0

64

128

Page 9: Класс!ная Cassandra

Чтение из кластера

resolved result

Данные

Хэш

Неправильный хэш

Read Repair

192

0

64

128

Page 10: Класс!ная Cassandra

Column Family

Ключ name0:byte[] ... nameN:byte[]byte[] value0:byte[] valueN:byte[]

timestamp0:long timestampN:long

Таблица “Х”

Ключ name0:byte[] ... nameK:byte[]

...

Порядок

Порядок

Таблица “Х”

Page 11: Класс!ная Cassandra

Запись изнутриname value ts

Memtable

Write (Key, Column)

Flusher Thread

SSTable 1 SSTable 2 SSTable 3 SSTable 4

Compaction Thread

SSTable 5

записывает

Commit Log

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

Запись на диск всегда последовательная!

Page 12: Класс!ная Cassandra

Чтение изнутриname value ts

Memtable

SSTable 1 SSTable 4 SSTable 5

resolveчасть данных 1

- get( Key, columnNames ... )- slice( Key, from, to, count, direction )- key_range( fromKey, toKey, count, slice(...) )

часть 2

часть 3

Page 13: Класс!ная Cassandra

Анатомия SSTable

- НОЛЬ чтений с диска, если строки нет и вам повезло- 1 чтение, если строки нет и не повезло- 2 чтения с диска для маленьких строк- 3 чтения - для больших

SSTable-5-Filter.db SSTable-5-Index.db SSTable-5-Data.db

Блум - фильтр

“Строка, возможно, есть”

Всегда в ОЗУ

Ключ => Смещение

Данные

Строки и Колонки

По-строчныеблум фильтры ииндексы для

длинных строк

Что дает:

Page 14: Класс!ная Cassandra

Разрешение конфликтов

RowKey = “Oleg_Anastasyev”

Column=”LV05HABA95142357516”

Value= $1,000,000

RowKey = “Oleg_Anastasyev”

Column=”LV05HABA95142357516”

Value= $10vs

Какое состояние верно ?

Memtable “AccountStatements”SSTable “AccountStatements-3456”

Page 15: Класс!ная Cassandra

Разрешение конфликтов

С более свежим timestamp.

RowKey = “Oleg_Anastasyev”

Column=”LV05HABA95142357516”

Value= $1,000,000

Timestamp = 13:00:05

RowKey = “Oleg_Anastasyev”

Column=”LV05HABA95142357516”

Value= $10

Timestamp = 13:00:01

vs

MemtableSSTable “AccStatements-3456”

Page 16: Класс!ная Cassandra

Потерянная модификация

1. Читаем AccountStatement Key=”Oleg”

(получили $10, TS=12:00:00)

2. Взнос $1,000,000

3. Сохраняем Key=”Oleg”, Value=$1,000,010 TS=12:00:01.000

1. Читаем AccountStatement Key=”Oleg”

(получили $10, TS=12:00:00)

2. Снимаем $1

3. Сохраняем Key=”Oleg”, Value=$9 TS=12:00:01.005

$10

$9

Page 17: Класс!ная Cassandra

Итог таковПреимущества:

- Высокая и стабильная скорость записи- Очень быстрое чтение отсутсвующего ключа- Скорость чтения не зависит от объема - Сортированные данные на диске

- Высокая доступность- Масштабирование и восстановление данных на ходу

- Резервное копирование не нужно- Эффективная эксплуатация в нескольких ЦОД

Недостатки:

- Нет ACID, нет откатов

- Нет детектора конфликтов- NoSQL => нет JOIN

О запросах думать зараннее Денормализация данных

Page 18: Класс!ная Cassandra

Устали от теории ?

Page 19: Класс!ная Cassandra

Класс! 4256

Классная задачка

Page 20: Класс!ная Cassandra

Класс! 4256 Вы и 4256

Классная задачка

Page 21: Класс!ная Cassandra

Класс! 4256 Вы и 4256

Классная задачка

Page 22: Класс!ная Cassandra

таблица

запросы– COUNT ( RefId,RefType=? ): 80% => 0– EXISTS( RefId,RefType,UserId=? ): 98% => Нет – RefId,RefType=? ORDER BY Created DESC -- кто классил ?

RefId:long RefType:byte UserId:long Created

9999999999 STATUS(2) 11111111111 11:00

Классная задачка

Вы и 4256

Page 23: Класс!ная Cassandra

как то скучно ...

таблица

запросы– COUNT ( RefId,RefType=? ): 80% => 0– EXISTS( RefId,RefType,UserId=? ): 98% => Нет – RefId,RefType=? ORDER BY Created DESC -- кто классил ?

RefId:long RefType:byte UserId:long Created

9999999999 STATUS(2) 11111111111 11:00

Классная задачка

Вы и 4256

Page 24: Класс!ная Cassandra

Классная задача

Page 25: Класс!ная Cassandra

Классная задача

Page 26: Класс!ная Cassandra

Классная задача

Больше в 8 раз!

Page 27: Класс!ная Cassandra

таблица

нагрузка 8х– 16 миллиардов показов в день (~ 300 000/сек)– 100 M класс!ов в день ( ~ 2500/сек )– 2TB данных

новый запрос– RefId,RefType=? ORDER BY ДрузьяСверху

длинный хвост– 40% EXISTS(RefId,UserId) не кешируются в принципе

RefId:long RefType:byte UserId:long Created9999999999 STATUS(2) 11111111111 11:00

Классная проблема

Page 28: Класс!ная Cassandra

уже есть:– 8 SQL кластеров (без учета резерва)– 12 кешей (увеличение количества большого эффекта не дает)– И они близки к пределу по CPU, дисковым операциям

Классная проблема

А мы хотим в 8 раз больше

Page 29: Класс!ная Cassandra

Добавить больше SQL– Уже есть 8, доставляем до 32– Дорого ( железо + лицензии MS)– Добавление SQL - ручная офлайн работа– Повторяем раз в полгода ( 64 => 128 =>256 )– Ненадежно

Добавить кешей– Много NOT EXISTS + длинный хвост => LRU кеш не работает– Значит нужно кешировать 100% Классов!– 2TB ОЗУ не дешево – ( и надо умножить на 2 или 3 для надежности )

Простые решения ?

Page 30: Класс!ная Cassandra

Упираем на хорошее– Дешевый NOT EXISTS ( отсекается Блум-фильтром )– Простая структура– Хвост хранится на дисках– Удобное масштабирование– Высокая доступность

Не попадая в плохое– Нет требований ACID– Eventual Consistency приемлемо– Класс!ы никогда не меняются– У нас есть время для compaction

Cassandra !

Page 31: Класс!ная Cassandra

LikeByRef

LikeCount

LikeByUser

Все класс!ы по сущности

Счетчики отдельно

Мои класс!ы

Класс!ная модель данных

Page 32: Класс!ная Cassandra

LikeByRef

Key Column Column Value TimestampType+RefId userId:byte[8] <null> Created

– EXISTS ( Type,RefId=?, UserId=?) 98% calls => “NOT EXISTS”– WHERE Type,RefId=? ORDER BY ДрузьяСверху LIMIT XX

Мы не хотим читать диск на этих запросах

...но Cassandra использует блум-фильтр только для отсечки строк

Класс!ная модель данных

Page 33: Класс!ная Cassandra

Колоночный блум-фильтрЧто делает

– Хранит пары (Key, Column name) прямо в SSTable *-Filter.db

Хорошо– Полностью убрали чтения с диска на NOT EXISTS– ... то есть 98% запросов идут только в память– больше фильтр => меньше false positives

Плохо– блум фильтры стали большими - сотни мегабайт– .. GC Promotion Failures (так как были в одном long[])– исправили (CASSANDRA-2466) в cassandra 1.0

Page 34: Класс!ная Cassandra

Классная модельLikeCountKey Column Column Value TimestampType+RefId nodeIp:byte[4] nodeCounter:int Created

– COUNT ( RefType,RefId=?) 80% calls => “NOT EXISTS”

Мы не хотим делать сетевые запросы если классов нет...но Cassandra всегда это делает для RR или пострадает консистентность

Page 35: Класс!ная Cassandra

и еще плохо

- DTO <-> hector <-> THRIFT <-> cassandra- THRIFT медленный и неудобный- Несконсистентные транзакции- Дополнительная коммуникация из-за RR- Кеш только LRU, некомпактный

cassandra

application server 1. COUNT()

2. EXISTS

Page 36: Класс!ная Cassandra

классное решение

application server

odnoklassniki-like

cassandra

one-nio

- Бакенд и Cassandra в той же JVM- Бакенд в том же ринге- Работает через one-nio транспорт

Page 37: Класс!ная Cassandra

Локальный доступ– запросы COUNT(RefId), EXISTS(RefId,UserId) проверяются по блум - фильтрам в памяти локальной ноды

Спец кеш счетчиков– более компактный, off heap– ... 40M элементов -> 1G RAM– сохраняется на диск для быстрого старта

– учитывает длинный хвост

классное решение

Page 38: Класс!ная Cassandra

Кеш счетчиков

m

0

64

128

Page 39: Класс!ная Cassandra

Кеш счетчиков

m

0

64

128

Page 40: Класс!ная Cassandra

Кеш счетчиков

m

0

64

128

Page 41: Класс!ная Cassandra

Кеш счетчиков

m

m * 50

m * 50

0

64

128

Page 42: Класс!ная Cassandra

Кеш счетчиков

- при изменении- на втором чтении- повторить раз в 8 ч

Фейковые изменения TS = TS

m

0

64

128

Page 43: Класс!ная Cassandra

– 12 cassandra nodes вместо 8 SQLs + резерв + 12 кешей– более надежная: RF = 3, в каждом ЦОД по реплике– более производительная: 1M бизнес запросов/сек– более быстрая: более чем в 10 раз, менее 1.5 мс в среднем– расширяемая: 12 -> 24 -> 48– быстрорастущая: 8 TB, + 15 G в день

профит

Page 45: Класс!ная Cassandra

connect.ok.ru

Можно узнать больше!