Олег Анастасьев "Ближе к Cassandra". Выступление на Cassandra Conf 2013

1,814 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,814
On SlideShare
0
From Embeds
0
Number of Embeds
551
Actions
Shares
0
Downloads
19
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Олег Анастасьев "Ближе к Cassandra". Выступление на Cassandra Conf 2013

  1. 1. Ближе к Cassandra Олег Анастасьев ведущий разработчик, команда платформы odnoklassniki.ru
  2. 2. 7 M онлайн 40M в день, 80M в месяц ! ~ 300 000 www страниц/сек, 20 ms на страницу >280 ГБит/сек ! > 6 600 серверов в 5 ЦОД 99.9% java
  3. 3. Cassandra @ * Начинали в 2010 - своя версия, основана на 0.6 - целились в: выживаемость при отказе ЦОД, масштабируемость, простота эксплуатации, адаптируемость * Сейчас - 23 разных кластера - 418 всего нод - 240 TB данных ! - пережили несколько отказов ЦОД
  4. 4. “Раз” - котенок ! самый быстрый
  5. 5. Класс! 103 927 Вы и 103 927
  6. 6. Виджет Класс! * Он везде - На каждой странице по несколько - В ленте активности - На сайтах в Интернетах ! * Он на всем - Картинки и альбомы - Видео - Посты и комментарии - Ссылки на внешние сайты Класс! 103 927
  7. 7. Виджет Класс! * Высоко нагруженный - 1 000 000 чтений/сек, 3 000 записей/сек ! * Сложный профиль Класс! 103 927 - Много чтений - Длинный хвост (40% чтений случайны) - Чувствительна к вариациям скорости - 3TB данных (9TB с RF) и растет - ~ 60 млрд класс!ов к ~6 млрд объектов
  8. 8. Простое решение SQL табличка 
 RefId:long RefType:byte UserId:long Created 9999999999 PICTURE(2) 11111111111 11:00 ! для отрисовки Вы и 4256 ! SELECT TOP 1 WHERE RefId,RefType,UserId=?,?,? (98% are NONE) ! SELECT COUNT (*) WHERE RefId,RefType=?,? (80% are 0) ! SELECT TOP N * RefId,RefType=? WHERE IsFriend(?,UserId)
  9. 9. Простая проблема SQL табличка 
 RefId:long RefType:byte UserId:long Created 9999999999 PICTURE(2) 11111111111 11:00 ! для отрисовки Вы и 4256 ! SELECT TOP 1 WHERE RefId,RefType,UserId=?,?,? (98% are NONE) = N >=1 ! SELECT COUNT (*) WHERE RefId,RefType=?,? (80% are 0) = M>N ! SELECT TOP N * RefId,RefType=? WHERE IsFriend(?,UserId) = N*140
  10. 10. Пробуем Cassandra LikeByRef ( refType byte, refId bigint, userId bigint, ! PRIMARY KEY ( (RefType,RefId), UserId) для отрисовки LikeCount ( refType byte, refId bigint, likers counter, ! PRIMARY KEY ( (RefType,RefId)) Вы и 4256 ! SELECT FROM LikeCount WHERE RefId,RefType=?,? (80% are 0) ! SELECT * FROM LikeByRef WHERE RefId,RefType,UserId=?,?,? (98% are NONE) = N*20%
  11. 11. >11 M iops * Пробуем решить по быстрому LikeByRef ( ! refType byte, refId bigint, ! userId bigint, ! ! PRIMARY KEY ( (RefType,RefId, UserId) ) ! SELECT TOP N * RefId,RefType=? WHERE IsFriend(?,UserId) - Нужен Order Pres Partitioner (Random не масштабируется) - Запросы по диапазону ключей (KeyRange) - Больше сетевого оверхеда - Партиций >10x, Размер данных > x2
  12. 12. Колоночный блум фильтр * Что делает - Хранит пары (PartKey, ColumnKey) в SSTable *-Filter.db ! И это хорошо - Убрали 98 % чтений с диска - Меньше ложных попаданий * Но все таки… - Они стали очень большими * Проблемы с GC Promotion Failures .. фиксим (CASSANDRA-2466)
  13. 13. Уже готово ? 1. COUNT() сервер приложений > 400 00 2. EXISTS cassandra - 2 похода для отрисовки (COUNT+RR) - THRIFT медленный, когда много клиентов - EXISTS() дает 200 Gbit/sec (140*8*1Mps*20%)
  14. 14. Совместить! get() : LikeSummary odnoklassniki-like Сетевой Бизнес Intf Кеш счетчиков cassandra Кеш соц. графа - one-nio remoting (быстрее родного nio в java) - клиенты знают топологию кластера
  15. 15. Вместе это хорошо * Быстрый запрос TOP N друзей 1. Берем друзей из кеша соц графа 2. Проверяем по блум фильтру в памяти 3. Читаем с диска пока получим N ! * Свои кеши - Специализированные под приложение ! * Свое объединение реплик данных - … можно находить и разрешать кофликты
  16. 16. Слушаем мутации // Implement it interface StoreApplyListener { boolean preapply(String key, ColumnFamily data); } // and register with CFS store=Table.open(..) .getColumnFamilyStore(..); store.setListener(myListener); * Регистрируем слушателя после применения логов но до госсипа ! * RowMutation.apply() и расширяем логику записей + На репликах, хинты, ReadRepairs
  17. 17. Счетчики с быстрым чтением * Кеш счетчиков LikeCount ( refType byte, refId bigint, ip inet, counter int PRIMARY KEY ( (RefType,RefId), - Off heap (sun.misc.Unsafe) - Компакен (30M in 1G RAM) - Читаем только кеш локальной ноды ! * Репликацию кеша - проблема холодного кеша реплик делаем (NOP) записи меньше чтений учитывает длинный хвост
  18. 18. Вариации скорости * Что делает Cassandra 1. Взять 1 ноду с данным и CL-1 - дайджест 2. Ждем данные и дайджест 3. Сравниваем и возвращаем (или RR) * Ноды притормаживают - Изза: SEDA, ротируем commit log , внезапно много IO, заткнулась сеть или пропала, внезапно много IO мимо кеша диска… * И что видят клиенты ? - Пики времени обработки запросов - Можно только ждать (до таймаута)
  19. 19. Read Latency leveling * “Параллельная” обработка чтений 1. Запрашиваем данные со всех реплик сразу 2. Ждем сколько надо CL ответов реплик ! * И это хорошо - Всегда минимальное время обработки - Та же нагрузка при отказе ЦОД ! * что (не так уж) плохо - “Дополнительная” нагрузка и трафик
  20. 20. More tiny tricks * Для SSD io - Deadline IO шедулер - 64k -> 4k размер запроса на чтение ! * Хинт Лог - Коммит лог для хинтов - Ждем доставки всех хинтов на старте ! * Селективый компактор - Чаще читаем из CF - чаще компактим
  21. 21. “Два” - котенок ! самый пухлый
  22. 22. * Сообщения в чатах - Читаем свежую страницу на открытии - длинный хвост (80%) для остальных - 150 млрд, 100 TB на дисках - Чтений больше: 120k в сек; 8k записей
  23. 23. Сообщение это структура Message ( chatId, msgId, ! created, type,userIndex,deletedBy,...
 text ) MessageCF ( chatId, msgId, ! data blob, ! PRIMARY KEY ( chatId, msgId ) - Все сообщения чата в 1 партиции - Каждое представлено блобом для уменьшения накладных расходов ! - Стало плохо Возможны конфиликтующие изменения одного сообщения
 (пользователи, антиспам, чистка,…)
  24. 24. Легкое разрешение конфликтов get get (version:ts1, data:d1) (version:ts1, data:d1) write( ts1, data2 ) delete(version:ts1) insert(version: ts2=now(), data2) Messages ( chatId, msgId, version timestamp, data blob PRIMARY KEY ( chatId, msgId, version ) write( ts1, data3 ) delete(version:ts1) insert(version: ts3=now(), data3) (ts2, data2) (ts3, data3) - merged on read
  25. 25. Специализированный кеш * Опять. Потому что можем - Off-heap (Unsafe) - Кеширует только свежайшие страницы - Пишет состояние в локальный (system) CF И ключи, и значения последовательное чтение на старте - Компрессия данных в памяти В 2 раза больше памяти бесплатно
  26. 26. Делим диски * 4U HDDx24, до 4 TB на сервер - Size tiered compaction = файл до 4 TB - RAID10 ? LCS ? ! * Делим CF на 256 кусочков * Стало хорошо - Более частые, но меньшие сбросы мемтаблиц - Столько же работы для компактора но более мелкими наборами - Можно распределять между дисками
  27. 27. Политика распределения * Из коробки - “Берем наиболее свободный по месту диск” * И теперь некоторые из них - слишком нагружены на ввод-вывод ! * По поколениям - На каждом диске хранится одинаковое количество sstables одного поколения работает лучше всех для ЖД
  28. 28. “Три” -
 Уродливый и страшный это-ж, братцы, Франкенштейн !
  29. 29. * Список чатов - мало данных (230GB) - есть горячий набор, короткий хвост (5%) - список часто пересортировывается - 130k чтений/сек, 21k записей/сек
  30. 30. Конфликтные изменения * List<ЧатOverview> в 1 блоб .. или мы получим много могилок ! * Много конфликтов все меняют 1 колонку ! * Определен алгоритм слияния * Нужно детектирования конфликтов
  31. 31. Векторные часы * Voldemort - byte[] ключ -> byte[] значение + ВЧ - Все клиенты - координаторы - Заменяемые виды хранилищ ! * Ну и заменили - На СС таблицы от CS 0.6 - Со специализированным кеш кеши. мы знаем как.
  32. 32. Скорость * Кластер из 3 нод, RF = 3 - Intel Xeon CPU E5506 2.13GHz 
 RAM: 48Gb, 1x HDD, 1x SSD ! * 8 байт ключ -> 1 KB значение ! * Дает - 75 k чтений/сек и 15 k записей
  33. 33. Зачем нам C* ? * Готовые компоненты РБД быстрое хранилище, gossip, надежные асинхронные сообщения, детектор сбоев, топология, последовательная обработка, ... * Данные могут быть структутированы сложнее, чем byte[] ключ -> byte[] значение * Выполнила наши цели * Сделано на java
  34. 34. СПАСИБО Олег Анастасьев ! oa@odnoklassniki.ru odnoklassniki.ru/oa @m0nstermind ! github.com/odnoklassniki shared-memory-cache кеш для java вне кучи и в разделяемой памяти one-nio ремотинг быстрее, чем java nio; с автомагической встроенной сериализацией

×