Класс!ная Cassandra

3,929 views
3,687 views

Published on

В этой презентации мы расскажем о своем опыте применения этого хранилища на примере одной из самых высоконагруженных подсистем — хранилища Класс!ов. В данный момент в системе хранится около 50 миллиардов записей о Класс!, что занимает в сумме около 8 Тб. Для того чтобы реализовать такое хранилище пришлось отойти от классического способа работы с Cassandra. Мы расскажем об этом, а также о том, как Cassandra устроена под капотом, её сильные и слабые стороны, какие решения мы принимали и что мы изменили в Cassandra, чтобы сделать наше хранилище более высокопроизводительным и надежным.

Published in: Technology
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,929
On SlideShare
0
From Embeds
0
Number of Embeds
225
Actions
Shares
0
Downloads
35
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Класс!ная Cassandra

  1. 1. Класс!ная CassandraОлег Анастасьевведущий разработчик,Одноклассники
  2. 2. > 6 M онлайн 290 000 страниц/сек, 20 ms на страницу >240 Гбит/сек> 5 000 серверов в 4 ЦОД 99.9% java
  3. 3. = NoSQL Высокодоступная РаспределеннаяСистема Управления Данными с Открытым Кодом
  4. 4. Cassandra @ Оценки фото Класс! Архив сообщений ... и много других
  5. 5. Введение в Cassandra ( сильно упрощенное )
  6. 6. Cassandra- Кластер, gossip - Масштабирование,- Партиционирование по ключу 0 восстановление на ходу- Высокая доступность- Поддержка нескольких ЦОД - Не нужны бакапы Строки токен(к) Строки токен(к) 192-... 0-63 192 64 R3 R1 Строки токен(к) Строки токен(к) 128-191 64-127 128 R2
  7. 7. Запись в кластер 0 THRIFT Изменение 192 64 HintStorage 128
  8. 8. Запись в кластер 0 THRIFT Изменение 192 64 HintStorage 128
  9. 9. Чтение из кластера 0 Данныеresolved result Хэш 192 64 Неправильный хэш Read Repair 128
  10. 10. Column Family ПорядокТаблица “Х” Ключ name0:byte[] ... nameN:byte[] byte[] value0:byte[] valueN:byte[] timestamp0:long timestampN:longТаблица “Х” Ключ name0:byte[] ... nameK:byte[] Порядок ...
  11. 11. Запись изнутри Write (Key, Column) name value ts Commit Log Memtable Flusher Thread записывает SSTable 1 SSTable 2 SSTable 3 SSTable 4Compaction Thread Сортировка слиянием SSTable 5 Запись на диск всегда последовательная!
  12. 12. Чтение изнутри name value ts часть данных 1resolve Memtable часть 2 часть 3 SSTable 1 SSTable 4 SSTable 5 - get( Key, columnNames ... ) - slice( Key, from, to, count, direction ) - key_range( fromKey, toKey, count, slice(...) )
  13. 13. Анатомия SSTable SSTable-5-Filter.db SSTable-5-Index.db SSTable-5-Data.db Данные Блум - фильтр Ключ => Смещение Строки и Колонки “Строка, возможно, есть” По-строчные Всегда в ОЗУ блум фильтры и индексы для длинных строкЧто дает: - НОЛЬ чтений с диска, если строки нет и вам повезло - 1 чтение, если строки нет и не повезло - 2 чтения с диска для маленьких строк - 3 чтения - для больших
  14. 14. Разрешение конфликтовSSTable “AccountStatements-3456” Memtable “AccountStatements”RowKey = “Oleg_Anastasyev” RowKey = “Oleg_Anastasyev”Column=”LV05HABA95142357516” Column=”LV05HABA95142357516” vsValue= $1,000,000 Value= $10 Какое состояние верно ?
  15. 15. Разрешение конфликтовSSTable “AccStatements-3456” MemtableRowKey = “Oleg_Anastasyev” RowKey = “Oleg_Anastasyev”Column=”LV05HABA95142357516” Column=”LV05HABA95142357516” vsValue= $1,000,000 Value= $10Timestamp = 13:00:05 Timestamp = 13:00:01 С более свежим timestamp.
  16. 16. Потерянная модификация $101. Читаем AccountStatement Key=”Oleg” 1. Читаем AccountStatement Key=”Oleg” (получили $10, TS=12:00:00) (получили $10, TS=12:00:00) 2. Взнос $1,000,000 3. Сохраняем Key=”Oleg”, 2. Снимаем $1 Value=$1,000,010 TS=12:00:01.000 3. Сохраняем Key=”Oleg”, Value=$9 TS=12:00:01.005 $9
  17. 17. Итог таковПреимущества: Недостатки:- Высокая и стабильная скорость записи - Нет ACID, нет откатов- Очень быстрое чтение отсутсвующего ключа - Нет детектора конфликтов- Скорость чтения не зависит от объема - NoSQL => нет JOIN- Сортированные данные на диске О запросах думать зараннее Денормализация данных- Высокая доступность- Масштабирование и восстановление данных на ходу- Резервное копирование не нужно- Эффективная эксплуатация в нескольких ЦОД
  18. 18. Устали от теории ?
  19. 19. Классная задачкаКласс! 4256
  20. 20. Классная задачкаКласс! 4256 Вы и 4256
  21. 21. Классная задачкаКласс! 4256 Вы и 4256
  22. 22. Классная задачка таблица RefId:long RefType:byte UserId:long Created 9999999999 STATUS(2) 11111111111 11:00 запросы– COUNT ( RefId,RefType=? ): 80% => 0 Вы и 4256– EXISTS( RefId,RefType,UserId=? ): 98% => Нет– RefId,RefType=? ORDER BY Created DESC -- кто классил ?
  23. 23. Классная задачка таблица RefId:long RefType:byte UserId:long Created 9999999999 STATUS(2) 11111111111 11:00 запросы– COUNT ( RefId,RefType=? ): 80% => 0 Вы и 4256– EXISTS( RefId,RefType,UserId=? ): 98% => Нет– RefId,RefType=? ORDER BY Created DESC -- кто классил ? как то скучно ...
  24. 24. Классная задача
  25. 25. Классная задача
  26. 26. Классная задачаБольше в 8 раз!
  27. 27. Классная проблема таблицаRefId:long RefType:byte UserId:long Created9999999999 STATUS(2) 11111111111 11:00 нагрузка 8х – 16 миллиардов показов в день (~ 300 000/сек) – 100 M класс!ов в день ( ~ 2500/сек ) – 2TB данныхновый запрос – RefId,RefType=? ORDER BY ДрузьяСверхудлинный хвост – 40% EXISTS(RefId,UserId) не кешируются в принципе
  28. 28. Классная проблемауже есть: – 8 SQL кластеров (без учета резерва) – 12 кешей (увеличение количества большого эффекта не дает) – И они близки к пределу по CPU, дисковым операциям А мы хотим в 8 раз больше
  29. 29. Простые решения ?Добавить больше SQL– Уже есть 8, доставляем до 32– Дорого ( железо + лицензии MS)– Добавление SQL - ручная офлайн работа– Повторяем раз в полгода ( 64 => 128 =>256 )– НенадежноДобавить кешей– Много NOT EXISTS + длинный хвост => LRU кеш не работает– Значит нужно кешировать 100% Классов!– 2TB ОЗУ не дешево– ( и надо умножить на 2 или 3 для надежности )
  30. 30. Cassandra !Упираем на хорошее– Дешевый NOT EXISTS ( отсекается Блум-фильтром )– Простая структура– Хвост хранится на дисках– Удобное масштабирование– Высокая доступностьНе попадая в плохое– Нет требований ACID– Eventual Consistency приемлемо– Класс!ы никогда не меняются– У нас есть время для compaction
  31. 31. Класс!ная модель данных LikeByRef Все класс!ы по сущности LikeCount Счетчики отдельно LikeByUser Мои класс!ы
  32. 32. Класс!ная модель данныхLikeByRef Key Column Column Value Timestamp Type+RefId userId:byte[8] <null> Created – EXISTS ( Type,RefId=?, UserId=?) 98% calls => “NOT EXISTS” – WHERE Type,RefId=? ORDER BY ДрузьяСверху LIMIT XX Мы не хотим читать диск на этих запросах ...но Cassandra использует блум-фильтр только для отсечки строк
  33. 33. Колоночный блум-фильтрЧто делает – Хранит пары (Key, Column name) прямо в SSTable *-Filter.dbХорошо – Полностью убрали чтения с диска на NOT EXISTS – ... то есть 98% запросов идут только в память – больше фильтр => меньше false positivesПлохо – блум фильтры стали большими - сотни мегабайт – .. GC Promotion Failures (так как были в одном long[]) – исправили (CASSANDRA-2466) в cassandra 1.0
  34. 34. Классная модельLikeCountKey Column Column Value TimestampType+RefId nodeIp:byte[4] nodeCounter:int Created – COUNT ( RefType,RefId=?) 80% calls => “NOT EXISTS” Мы не хотим делать сетевые запросы если классов нет ...но Cassandra всегда это делает для RR или пострадает консистентность
  35. 35. и еще плохо application server 1. COUNT() 2. EXISTS cassandra- DTO <-> hector <-> THRIFT <-> cassandra- THRIFT медленный и неудобный- Несконсистентные транзакции- Дополнительная коммуникация из-за RR- Кеш только LRU, некомпактный
  36. 36. классное решение application server one-nio odnoklassniki-like cassandra- Бакенд и Cassandra в той же JVM- Бакенд в том же ринге- Работает через one-nio транспорт
  37. 37. классное решениеЛокальный доступ – запросы COUNT(RefId), EXISTS(RefId,UserId) проверяются по блум - фильтрам в памяти локальной нодыСпец кеш счетчиков – более компактный, off heap – ... 40M элементов -> 1G RAM – сохраняется на диск для быстрого старта – учитывает длинный хвост
  38. 38. Кеш счетчиков 0 m 64 128
  39. 39. Кеш счетчиков 0 m 64 128
  40. 40. Кеш счетчиков 0 m 64 128
  41. 41. Кеш счетчиков 0 m * 50 m 64 m * 50 128
  42. 42. Кеш счетчиков Фейковые 0 изменения TS = TS m 64 - при изменении - на втором чтении 128 - повторить раз в 8 ч
  43. 43. профит– 12 cassandra nodes вместо 8 SQLs + резерв + 12 кешей– более надежная: RF = 3, в каждом ЦОД по реплике– более производительная: 1M бизнес запросов/сек– более быстрая: более чем в 10 раз, менее 1.5 мс в среднем– расширяемая: 12 -> 24 -> 48– быстрорастущая: 8 TB, + 15 G в день
  44. 44. Можно узнать больше!Odnoklassniki.ru Интеграция с Odnoklassniki.ruhttp://v.ok.ru http://connect.ok.ruone-nio Cassandraslideshare.net/m0nstermind/presentationsgithub.com/odnoklassniki/one-nio github.com/odnoklassniki/apache-cassandra cassandra.apache.org Олег Анастасьев oa@odnoklassniki.ru odnoklassniki.ru/oa
  45. 45. Можно узнать больше!connect.ok.ru

×