SlideShare a Scribd company logo
Класс!ная Cassandra

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

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

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


> 5 000 серверов в 4 ЦОД
       99.9% java
Cassandra @
    Оценки фото

    Класс!

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

    ... и много других
Введение в Cassandra
     ( сильно упрощенное )
Cassandra
- Кластер, gossip                                                         - Масштабирование,
- Партиционирование по ключу                     0                            восстановление на ходу
- Высокая доступность
- Поддержка нескольких ЦОД                                                - Не нужны бакапы

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

                                   192-...                     0-63
                                                                                R1
                         192                                             64
                    R3
                               Строки токен(к)         Строки токен(к)

                                  128-191                  64-127


                                                 128
                                                          R2
Запись в кластер
                               0
     THRIFT


                   Изменение


          192                      64


  Hint
Storage



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


                   Изменение


          192                      64


  Hint
Storage



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

                   Данные
resolved
 result

                              Хэш

           192                               64


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


            Read Repair

                                  128
Column Family
                 Порядок
Таблица “Х”
  Ключ           name0:byte[]            ...   nameN:byte[]
  byte[]         value0:byte[]                 valueN:byte[]
                 timestamp0:long               timestampN:long


Таблица “Х”
  Ключ           name0:byte[]            ...   nameK:byte[]
       Порядок




                                   ...
Запись изнутри
  Write (Key, Column)              name        value      ts
                                                                                Commit Log

                                                  Memtable

      Flusher Thread
                                                       записывает

                               SSTable 1         SSTable 2          SSTable 3   SSTable 4


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


                                                   SSTable 5

Запись на диск всегда последовательная!
Чтение изнутри
                                                     name     value     ts

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

                                                             Memtable
                                       часть 2


               часть 3



          SSTable 1          SSTable 4           SSTable 5



               -   get( Key, columnNames ... )
               -   slice( Key, from, to, count, direction )
               -   key_range( fromKey, toKey, count, slice(...) )
Анатомия SSTable
   SSTable-5-Filter.db                   SSTable-5-Index.db                  SSTable-5-Data.db

                                                                                  Данные

     Блум - фильтр                      Ключ => Смещение                    Строки и Колонки

“Строка, возможно, есть”
                                                                              По-строчные
     Всегда в ОЗУ                                                            блум фильтры и
                                                                                индексы
                                                                                   для
                                                                             длинных строк


     Что дает:             - НОЛЬ чтений с диска, если строки нет и вам повезло
                           - 1 чтение, если строки нет и не повезло
                           - 2 чтения с диска для маленьких строк
                           - 3 чтения - для больших
Разрешение конфликтов
SSTable “AccountStatements-3456”              Memtable “AccountStatements”
RowKey = “Oleg_Anastasyev”                    RowKey = “Oleg_Anastasyev”

Column=”LV05HABA95142357516”                  Column=”LV05HABA95142357516”
                                         vs
Value= $1,000,000                             Value= $10




                               Какое состояние верно ?
Разрешение конфликтов
SSTable “AccStatements-3456”               Memtable
RowKey = “Oleg_Anastasyev”                 RowKey = “Oleg_Anastasyev”

Column=”LV05HABA95142357516”               Column=”LV05HABA95142357516”
                                      vs
Value= $1,000,000                          Value= $10

Timestamp = 13:00:05                       Timestamp = 13:00:01


                       С более свежим timestamp
                                   .
Потерянная модификация
                                         $10


1. Читаем 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
Итог таков
Преимущества:                                  Недостатки:

• Высокая и стабильная скорость записи         • Нет ACID, нет откатов
                                               • Нет детектора конфликтов
• Очень быстрое чтение отсутсвующего ключа     • NoSQL => нет JOIN
• Скорость чтения не зависит от объема                 О запросах думать зараннее
• Сортированные данные на диске                        Денормализация данных

• Нет 1 точки отказа
• Высокая доступность
• Масштабирование и восстановление данных на
  ходу
• Резервное копирование не нужно
• Эффективная эксплуатация в нескольких ЦОД
Устали от теории ?
Классная задачка
Класс! 4256
Классная задачка
Класс! 4256   Вы и 4256
Классная задачка
Класс! 4256   Вы и 4256
Классная задачка
  таблица
 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 -- кто классил ?
Классная задачка
  таблица
 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 -- кто классил ?




                                          как то скучно ...
Классная задача
Классная задача
Классная задача




x8
Классная проблема
 таблица
RefId:long              RefType:byte     UserId:long     Created
9999999999              STATUS(2)        11111111111     11:00


 нагрузка 8х
   – 16 миллиардов показов в день (~ 300 000/сек)
   – 100 M класс!ов в день ( ~ 2500/сек )
   – 2TB данных
новый запрос
   – RefId,RefType=? ORDER BY ДрузьяСверху
длинный хвост
   – 40% EXISTS(RefId,UserId) не кешируются в принципе
Классная проблема
уже есть:
            – 8 SQL кластеров (без учета резерва)
            – 12 кешей (увеличение количества большого эффекта не дает)
            – И они близки к пределу по CPU, дисковым операциям


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



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


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


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



 LikeByUser   Мои класс!ы
Класс!ная модель данных
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 использует блум-фильтр только для отсечки строк
Колоночный блум-фильтр
• что делает
– Хранит пары (Key, Column name) прямо в SSTable *-Filter.db


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

• плохо
– блум фильтры стали большими - сотни мегабайт
– .. GC Promotion Failures (так как были в одном long[])
– исправили (CASSANDRA-2466) в cassandra 1.0
Классная модель
LikeCount
Key                   Column                     Column Value                Timestamp
Type+RefId            nodeIp:byte[4]             nodeCounter:int             Created




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



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


                                                        1. COUNT()
                             application server




                                            2. EXISTS

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


                          application server   one-nio



                                                         odnoklassniki-like


                                                                cassandra
- Бакенд и Cassandra в той же JVM
- Бакенд в том же ринге
- Работает через one-nio транспорт
классное решение
• локальный доступ
– запросы COUNT(RefId), EXISTS(RefId,UserId)
  проверяются по блум - фильтрам в памяти локальной ноды



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

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




                     m
                64




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




                     m
                64




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




                     m
                64




     128
Кеш счетчиков
     0
           m * 50




                         m
                    64




           m * 50
     128
Кеш счетчиков
           Фейковые
     0     изменения
           TS = TS
                       - при изменении
                       - на втором чтении
                       - повторить раз в 8 ч

                           m
                  64




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


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


one-nio
                                                              Cassandra
slideshare.net/m0nstermind/presentations
                                                              github.com/odnoklassniki/apache-cassandra
github.com/odnoklassniki/one-nio
                                                              cassandra.apache.org


                                            Олег Анастасьев
                                            oa@odnoklassniki.ru
                                            odnoklassniki.ru/oa
Интересно?
connect.ok.ru
                Можно узнать больше !

More Related Content

PDF
Вы решили написать собственное хранилище, Илья Космодемьянский
PDF
Евгений Тихонов "Введение в Cassandra". Выступление на Cassandrd conf 2013
PDF
Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassa...
PDF
Евгений Курпилянский "Индексирование поверх Cassandra". Выступление на Cassan...
PPTX
Ольга Соболева и Кирилл Иванов "Обработка транзакций на примере телекоммуника...
PDF
Александр Соловьев "Cassandra in-e commerce". Выступление на Cassandra conf 2013
PDF
CQL3 and Data Modeling 101 with Apache Cassandra
PDF
Jonathan Ellis "Apache Cassandra 2.0 and 2.1". Выступление на Cassandra conf ...
Вы решили написать собственное хранилище, Илья Космодемьянский
Евгений Тихонов "Введение в Cassandra". Выступление на Cassandrd conf 2013
Aleksey Yeschenko "Моделирование данных с помощью CQL3". Выступление на Cassa...
Евгений Курпилянский "Индексирование поверх Cassandra". Выступление на Cassan...
Ольга Соболева и Кирилл Иванов "Обработка транзакций на примере телекоммуника...
Александр Соловьев "Cassandra in-e commerce". Выступление на Cassandra conf 2013
CQL3 and Data Modeling 101 with Apache Cassandra
Jonathan Ellis "Apache Cassandra 2.0 and 2.1". Выступление на Cassandra conf ...

Viewers also liked (20)

PPTX
Максим Сычев и Александр Коковин "Как мы переезжали на Cassandra". Выступлени...
PDF
Иван Бурмистров "Строго ориентированная последовательность временных событий"...
PDF
Олег Анастасьев "Ближе к Cassandra". Выступление на Cassandra Conf 2013
PDF
Javantura v2 - Data modeling with Apapche Cassandra - Marko Švaljek
PDF
Платформа для видео сроком в квартал. Александр Тоболь.
PPTX
Apache Cassandra, part 2 – data model example, machinery
PDF
Александр Сабинин "Организация динамической циклической очереди задач для ска...
PDF
Класс!ная Cassandra
PDF
Java Runtime: повседневные обязанности JVM
PDF
C*ollege Credit: Data Modeling for Apache Cassandra
PPTX
Introduction in CUDA (1-3)
PDF
Cassandra 101
PDF
Франкенштейнизация Voldemort или key-value данные в Одноклассниках. Роман Ан...
PDF
За гранью NoSQL: NewSQL на Cassandra
PPT
Алексей Чумаков. Apache Cassandra на реальном проекте
PPTX
Apache Cassandra. Ещё одно NoSQL хранилище (Владимир Климонтович)
PPTX
Введение в Apache Cassandra
PPTX
Apache Cassandra, part 1 – principles, data model
PPTX
Cassandra: быстрая запись данных в высоконагруженных системах
PDF
Signal Digital: The Skinny on Wide Rows
Максим Сычев и Александр Коковин "Как мы переезжали на Cassandra". Выступлени...
Иван Бурмистров "Строго ориентированная последовательность временных событий"...
Олег Анастасьев "Ближе к Cassandra". Выступление на Cassandra Conf 2013
Javantura v2 - Data modeling with Apapche Cassandra - Marko Švaljek
Платформа для видео сроком в квартал. Александр Тоболь.
Apache Cassandra, part 2 – data model example, machinery
Александр Сабинин "Организация динамической циклической очереди задач для ска...
Класс!ная Cassandra
Java Runtime: повседневные обязанности JVM
C*ollege Credit: Data Modeling for Apache Cassandra
Introduction in CUDA (1-3)
Cassandra 101
Франкенштейнизация Voldemort или key-value данные в Одноклассниках. Роман Ан...
За гранью NoSQL: NewSQL на Cassandra
Алексей Чумаков. Apache Cassandra на реальном проекте
Apache Cassandra. Ещё одно NoSQL хранилище (Владимир Климонтович)
Введение в Apache Cassandra
Apache Cassandra, part 1 – principles, data model
Cassandra: быстрая запись данных в высоконагруженных системах
Signal Digital: The Skinny on Wide Rows
Ad

Similar to CodeFest 2013. Анастасьев О. — Класс!ная Cassandra (20)

PDF
ОПК № 3 – Машинное представление целых чисел, символов, строк
PPTX
MyRocks: табличный движок для MySQL на основе RocksDB
PPTX
MyRocks Табличный Движок для MySQL / Алексей Майков (Facebook) / Сергей Петру...
PPTX
Опыт внедрения и использования распределенной системы хранения данных на осно...
PPTX
High Load
PPTX
Движок LMDB — особенный чемпион / Юрьев Леонид (Петер-Сервис R&D)
PDF
Что особенного в СУБД для данных в оперативной памяти / Константин Осипов (Ta...
PPTX
Эффективное использование x86-совместимых CPU (Алексей Тутубалин)
PDF
Метаданные для кластера: гонка key-value-героев / Руслан Рагимов, Светлана Ла...
PPTX
Доклад на Highload-2012
PPT
Низкоуровневые оптимизации. Андрей Аксенов. Unigine Open Air 2013
PDF
Kalugin balashov
PDF
Задача о ближайшем кодовом слове. Коды Галлагера—Сипсера—Шпильмана
PPT
Лекция № 2 Организация ЭВМ и систем
PPT
Лекция №2 Организация ЭВМ и систем
DOCX
C:\fakepath\кмсзи экз
PDF
Антон Потапов — С++ контейнеры и многопоточность: вместе или врозь?
PDF
Traditional relational databases architecture
PDF
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
PDF
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
ОПК № 3 – Машинное представление целых чисел, символов, строк
MyRocks: табличный движок для MySQL на основе RocksDB
MyRocks Табличный Движок для MySQL / Алексей Майков (Facebook) / Сергей Петру...
Опыт внедрения и использования распределенной системы хранения данных на осно...
High Load
Движок LMDB — особенный чемпион / Юрьев Леонид (Петер-Сервис R&D)
Что особенного в СУБД для данных в оперативной памяти / Константин Осипов (Ta...
Эффективное использование x86-совместимых CPU (Алексей Тутубалин)
Метаданные для кластера: гонка key-value-героев / Руслан Рагимов, Светлана Ла...
Доклад на Highload-2012
Низкоуровневые оптимизации. Андрей Аксенов. Unigine Open Air 2013
Kalugin balashov
Задача о ближайшем кодовом слове. Коды Галлагера—Сипсера—Шпильмана
Лекция № 2 Организация ЭВМ и систем
Лекция №2 Организация ЭВМ и систем
C:\fakepath\кмсзи экз
Антон Потапов — С++ контейнеры и многопоточность: вместе или врозь?
Traditional relational databases architecture
Доклад Сергея Аверина на CodeFest-2013. "MySQL+HandlerSocket=NoSQL".
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...
Ad

More from CodeFest (20)

PDF
Alexander Graebe
PDF
Никита Прокопов
PPTX
Денис Баталов
PDF
Елена Гальцина
PDF
Александр Калашников
PDF
Ирина Иванова
PDF
Marko Berković
PDF
Денис Кортунов
PDF
Александр Зимин
PDF
Сергей Крапивенский
PDF
Сергей Игнатов
PDF
Николай Крапивный
PDF
Alexander Graebe
PDF
Вадим Смирнов
PDF
Константин Осипов
PDF
Raffaele Rialdi
PDF
Максим Пугачев
PDF
Rene Groeschke
PDF
Иван Бондаренко
PDF
Mete Atamel
Alexander Graebe
Никита Прокопов
Денис Баталов
Елена Гальцина
Александр Калашников
Ирина Иванова
Marko Berković
Денис Кортунов
Александр Зимин
Сергей Крапивенский
Сергей Игнатов
Николай Крапивный
Alexander Graebe
Вадим Смирнов
Константин Осипов
Raffaele Rialdi
Максим Пугачев
Rene Groeschke
Иван Бондаренко
Mete Atamel

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

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