44
Олег Анастасьев ведущий разработчик, Одноклассники.ру Класс!ная Cassandra

CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

Олег Анастасьев

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

Класс!ная Cassandra

Page 2: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

> 6 M онлайн

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

>240 Гбит/сек

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

Page 3: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

Оценки фото

Класс!

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

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

Cassandra @

Page 4: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

Page 5: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

Cassandra0

64

128

192

Data Range

00-64

R1

R3

R2

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

0-63

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

64-127

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

128-191

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

192-...

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

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

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

Page 6: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

192

Data Range

00-64

HintStorage

THRIFT

Изменение

0

64

128

Page 7: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

192

Data Range

00-64

HintStorage

THRIFT

Изменение

0

64

128

Page 8: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

resolved result

Данные

Хэш

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

Read Repair

192

0

64

128

Page 9: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

Column Family

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

timestamp0:long timestampN:long

Таблица “Х”

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

...

Порядок

Порядок

Таблица “Х”

Page 10: CodeFest 2013. Анастасьев О. — Класс!ная 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 11: CodeFest 2013. Анастасьев О. — Класс!ная 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 12: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

Анатомия SSTable

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

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

Блум - фильтр

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

Всегда в ОЗУ

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

Данные

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

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

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

Что дает:

Page 13: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

RowKey = “Oleg_Anastasyev”

Column=”LV05HABA95142357516”

Value= $1,000,000

RowKey = “Oleg_Anastasyev”

Column=”LV05HABA95142357516”

Value= $10vs

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

Memtable “AccountStatements”SSTable “AccountStatements-3456”

Page 14: CodeFest 2013. Анастасьев О. — Класс!ная 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 15: CodeFest 2013. Анастасьев О. — Класс!ная 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 16: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

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

• Нет 1 точки отказа

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

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

Недостатки:

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

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

Page 17: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

Page 18: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

Класс! 4256

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

Page 19: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

Класс! 4256 Вы и 4256

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

Page 20: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

Класс! 4256 Вы и 4256

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

Page 21: CodeFest 2013. Анастасьев О. — Класс!ная 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 22: CodeFest 2013. Анастасьев О. — Класс!ная 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: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

Page 24: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

Page 25: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

x 8

Page 26: CodeFest 2013. Анастасьев О. — Класс!ная 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 27: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

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

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

Page 28: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

• Добавить кешей– Много NOT EXISTS + длинный хвост => LRU кеш не работает– Значит нужно кешировать 100% Классов!

– 2TB ОЗУ не дешево – ( и надо умножить на 2 или 3 для надежности )

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

Page 29: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

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

Cassandra !

Page 30: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

LikeByRef

LikeCount

LikeByUser

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

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

Мои класс!ы

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

Page 31: CodeFest 2013. Анастасьев О. — Класс!ная 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 32: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

Колоночный блум-фильтр• что делает– Хранит пары (Key, Column name) прямо в SSTable *-Filter.db

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

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

Page 33: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

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

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

Page 34: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

и еще плохо

cassandra

application server1. COUNT()

2. EXISTS

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

Page 35: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

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

odnoklassniki-like

cassandra

one-nioapplication server

Page 36: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

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

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

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

Page 37: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

Data Range

00-64

m

0

64

128

Page 38: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

Data Range

00-64

m

0

64

128

Page 39: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

Data Range

00-64

m

0

64

128

Page 40: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

Data Range

00-64

m

m * 50

m * 50

0

64

128

Page 41: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

Data Range

00-64

m

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

0

64

128

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

Page 42: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

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

профит

Page 43: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

Интересно?Можно узнать больше !

Олег Анастасьев

[email protected]/oa

one-nio

slideshare.net/m0nstermind/presentationsgithub.com/odnoklassniki/one-nio

Cassandragithub.com/odnoklassniki/apache-cassandracassandra.apache.org

Odnoklassniki.ru

http://v.ok.ruИнтеграция с Odnoklassniki.ru

http://connect.ok.ru

Page 44: CodeFest 2013. Анастасьев О. — Класс!ная Cassandra

connect.ok.ru

Интересно?Можно узнать больше !