Велосипедостраительство в nosql, строим собственное nosql...
DESCRIPTION
Слайды к докладу Highload dev Санкт-ПетербургTRANSCRIPT
Когда надо изобретать свой велосипед? Строим NoSQL хранилище в приемлемые
сроки
Календарев Александр
Программист РБК-Медиа
2013 dev.it-portfolio.net
О чём доклад
- о велосипедах
- NoSQL
- key/value хранилищах
- это очень просто
- Сделай сам
dev.it-portfolio.net 2
О велосипедах
dev.it-portfolio.net 3
О велосипедах
dev.it-portfolio.net 4
О велосипедах
dev.it-portfolio.net 5
О велосипедах
dev.it-portfolio.net 6
- Под конкретные условия местности свой велосипед
- Велосипеды эволюционирует, как впрочем и все на свете, в том числе системы хранения данных
- Следовательно, всегда полезно думать над их улучшением
- Значить, и стоит пытаться изобрести что-то новое
-
О велосипедах
dev.it-portfolio.net 7
- Под конкретные условия местности свой велосипед
- Велосипеды эволюционирует, как впрочем и все на свете, в том числе системы хранения данных
- Следовательно, всегда полезно думать над их улучшением
- Значить, и стоит пытаться изобрести что-то новое
- Или украсть идею и приспособить под свои нужды
О велосипедах
dev.it-portfolio.net 8
- Может получиться
О велосипедах
dev.it-portfolio.net 9
- Может получиться
- А может и нет
О велосипедах
dev.it-portfolio.net 10
- Может получиться
- А может и нет
- Это как повезет
О велосипедах
dev.it-portfolio.net 11
- Может получиться
- А может и нет
- Но в любом случае Вы всегда останетесь в плюсе:
- получите новый опыт и знание
О чём доклад
- о велосипедах
- NoSQL
- key/value хранилищах
- это очень просто
- Сделай сам
dev.it-portfolio.net 12
NoSQL
- Термин озвучен 1991 Carlo Strozzi
- Carlo Strozzi 1998 представил ”NoSQL RDBMS, Copyright (C)”, язык запросов 4GL
- 2009 на “Open Source” Конференции применили этот термин ко всем хранилищам, не относящимся к RDBMS
dev.it-portfolio.net 13
- Документно-ориентированные БД
- Key/value хранилища
- Поколоночные БД
- Графовые БД
Подробнее http://nosql-database.org/
dev.it-portfolio.net 14
Документно-ориентированные
- Данные представлены в виде документов
- Форматы документы:
- XML: BerkeleyXML (XQuery), Sedna, Tamino (XQL)
- JSON/BSON: MondoDb(BSON), CoachDb(JSON)
- msgpack: Kumofs, tarantool 2.0
Рекомендуется использовать для слабо структурированной информации
dev.it-portfolio.net 15
Key/value хранилища
Key-value хранилища запоминают и извлекают документы по ключу.
Распределенные хеш-таблицы (DHT) Пример: Riak, Voldemort, aerospike
Key/value хранилищa Пример: Redis, Tokyo/Kyoto Tyrant , tarantool 1.5, MemcacheDb
dev.it-portfolio.net 16
Поколоночные БД
- Данные собраны в колонки и представляют собой хеш таблицы.
dev.it-portfolio.net 17
Поколоночные БД
Преимущества:
- быстрая вставка,
- где документ представляем много колонок
- агрегирующие запросы в разы выше
Примеры: MonetDb, Accumulo, Vertica, Teradata
Недостаток: сложность загрузки данных
Cassandra, Hbase – не имеют поколоночную модель данных (технология SSTAble)
dev.it-portfolio.net 18
Графовые БД
Данные в виде сетевой модели
dev.it-portfolio.net 19
Пример: Neo4, InfoGrid, GraphBase, DEX
NoSQL сравнение моделей хранения
dev.it-portfolio.net 20
key/value документно-ориентированные
RDBMS поколоночно-ориентированные
О чём доклад
- о велосипедах
- NoSQL
- key/value хранилищах
- это очень просто
- Сделай сам
dev.it-portfolio.net 21
Key/Value Хранилище
- Index и Массива данных (bucket)
- Сетевой части
- Вспомогательных Tools :
- Конфигурация
- Репликация
- Мониторинг
dev.it-portfolio.net 22
Index + Bucket
dev.it-portfolio.net 23
Index
- Hash (хеш) - Теоретически доступ/вставка за пост время: O(a)
- Поиск строго по ключу (операция равно).
- BTree (двоичное дерево) - Поиск по диапазону
- Теоретически доступ за O(log2(n) ÷ n) или O(h)
- Удаление – очень дорого O(l *log2(n) )
Недостаток: разбалансировка
Разновидности: Btree+, AVL-Tree, RB-tree, 2-3-tree …
dev.it-portfolio.net 24
Hash таблица
dev.it-portfolio.net 25
Хеш-функция: crc32/64, md5, Jenkins, Murmur
Масив данных [bucket] для хранения
f = crc32(key) % n
Hash таблица
dev.it-portfolio.net 26
Так как объем Банк данных конечный, то возможна коллизия: Sabdra Dee & John Smeet
Hash
dev.it-portfolio.net 27
Хеш таблицу характеризуют – Ёмкость bucket – Разреженность массива – Длинна элемента массива
Хеш функция
Key 1
Key 51
Данные
Данные
Key 2 Длинные данные . . . . . .
Длинные Данные часть II
коллизия
Длинные данные
f = key % n
О чём доклад
- о велосипедах
- NoSQL
- key/value хранилищах
- это очень просто , cделай сам
dev.it-portfolio.net 28
Что надо сделать?
- Понять требования
- Изучить существующие решения
- Найти подходящее API:
- BerkeleyDb
- dict, qhash,
- Tokyo Cabinet
- LevelDb
- Sophia
dev.it-portfolio.net 29
Что надо сделать?
- Понять требования
- Изучить существующие решения
- Найти подходящее API
- Сделать тесты
- Выбрать сетевую модель: - Однотредовая (corotine)/многотредовая модель
- block/nonblock: select, poll, epoll, kqueue
- libevent, libev (взять существующие библ.)
- Найти готовый кусок кода
dev.it-portfolio.net 30
Что надо сделать?
- Понять требования
- Изучить существующие решения
- Найти подходящее API
- Сделать тесты
- Выбрать сетевую модель
- Определиться с протоколом.
dev.it-portfolio.net 31
О проекте
- Служба знакомств
- 50 млн. анкет
- 25 млн. активных
- 25-90 тыс. сессий
dev.it-portfolio.net 32
О проекте (функциональная часть)
- Просмотр и поиск анкет
- Система сообщений
- Голосовалки
- Симпатии, Лайки
- Сбор статистики
- Геосервис : кто рядом.
dev.it-portfolio.net 33
Что хотелось хранить?
- Результаты голосований
- Лайки
- Информация о просмотрах (счетчики)
- Геоданные
dev.it-portfolio.net 34
Лайки, голосовалки, просмотры
dev.it-portfolio.net 35
Bob: 01
Alice Counter: 1 Кто : 01
Лайки, голосовалки, просмотры
dev.it-portfolio.net 36
Bob: 01
Alice Counter: 2 Кто : 01, 02
Carol : 02
Лайки, голосовалки, просмотры
dev.it-portfolio.net 37
Bob: 01
Alice Counter: 3 Кто : 01, 02, 05
Carol : 02
Carlos : 05
Что хотелось?
- Простую функциональность:
- get(key)
- set(key)
- increment ( key )
- Кандидаты:
redis – можно использовать через Хеши
tarantool – удобный встроенный API (Lua)
dev.it-portfolio.net 38
Что хотелось?
- Простую функциональность;
get/set, Increment ( key1 , key2 )
- Персистентность
если упало, то данные не потерялись
dev.it-portfolio.net 39
Что хотелось?
- Простую функциональность
- Персистентность
- Что-то не сложное и быстрое
- не занимающее много места
- MongoDb такое же сложное, как MySQL
dev.it-portfolio.net 40
Что хотелось?
- Простую функциональность:
- Персистентность
- Что-то не сложное
- Не memory-only
- вдруг не хватит места:
- redis, tarantool не подходят
- Tokyo Tyrant – сложно реализовать лайки
dev.it-portfolio.net 41
Протокол
- Разработать свой Преимущества: учтены все особенности
- Взять существующий
Преимущества: не нужно разрабатывать клиенты
Недостатки: необходимо расширение, доработка под свои особенности
dev.it-portfolio.net 42
Протокол взять существующий
- Бинарный: protobuf, msgpack, memcached-bin, Apache-thrift, Apache-Avro, BSON,…
компактнее, быстрее, сложнее отладка
- Текстовый: XML, JSON, memcached, redis, …
Проще отладка
Есть утилиты: telnet, nc, memget, redis-cli
dev.it-portfolio.net 43
Протокол memcached
- GET ˽ [key] \r\n
- SET ˽ [key] ˽ [flag] ˽ [expire] ˽ [bytes] \r\n
- INCR ˽ [key] ˽ [value] ˽ [NOREPLAY] \r\n
- DELETE ˽ [key] ˽ [NOREPLAY] \r\n
- STATS \r\n
- FLUSH_ALL\r\n
dev.it-portfolio.net 44
Расширяем протокол
- Добавляем новые служебные команды: - FLUSH ˽ 1\r\n
- SHOW INI\r\n
- STAT CLEAR \r\n
- Расширяем существующие команды через ключ: - key: prefix.key[.subkey]
- Вводим понятие относительная адресация /
- Вводим понятие символьный вид #
dev.it-portfolio.net 45
Философия построения хранилища
- Используем понятие «Банк данных»
Банк данных – обособленный массив данных, место для хранения (bucket)
- Разбиваем данные по функциональности: лайки, голосования, просмотры
- Каждой сущности по своему банку.
- Номер банка определен префиксом ключа
dev.it-portfolio.net 46
Принцип построения хранилища
Номер банка определен префиксом ключа
dev.it-portfolio.net 47
GET 1.23456 Банк 1
Банк 2
Банк 3
GET 3.23456
GET 2.23456
Key prefix key 32 bit 32 bit
``
Принцип построения хранилища
Номер банка определен префиксом ключа Несколько банков могут быть объединены в одну физическую хеш таблицу (определяется конфигом) Достоинство такого распределения: • уменьшаем нагрузку на каждую хеш таблицу • Шаг к масштабированию • Распределение по типу использования
dev.it-portfolio.net 48
Типы банков
dev.it-portfolio.net 49
- Бинарные данные
- Символьные данные
- Счетчики [4 байта]
- «Индексные данные» на базе RB-tree
Индексные данные могут быть привязаны к счетчикам
Привязка осуществляется в конфиге.
Реализация счетчика просмотров
Счетчики просмотров:
INCR ˽ 1.5 ˽ 1 \r\n ключ анкеты = 5
SET˽ 1.5 ˽ 0 ˽ 0 ˽ 1 \r\n 0 \r\n сброс
50
Реализация лайка
- Увеличение счетчика Алисы :
INCR ˽ 1.5 ˽ 1 \r\n ключ Алисы = 5
- Добавляем в хеш Алисы ключ Боба:
SET ˽ 2.5.1 ˽0˽0˽1\r\n1\r\n ключ Боба = 1
dev.it-portfolio.net 51
Bob:01
Alice
Реализация лайка
Однако если расширить протокол:
INCR ˽ 2.5.1/1 ˽ 1 \r\n
Вместо двух обращений – одно.
dev.it-portfolio.net 52
Bob:01
Alice
key
Реализация лайка
dev.it-portfolio.net 53
- Вариант 1, как сортированный массив.
- Доступ за ln(n), n = 100 – 4 000 ( 7-14 шагов )
- Трудности с алгоритмом Garbage Collector.
- Вариант 2, используем Tree индекс
- Индекс составной 64 bit: key1 key2
- Выборка диапазона Key1 0x00 - Key1 0xFFFFFFFF
32 bit 32 bit ``
Расширяем протокол
Вводим понятие символьный вид #
Запомнили в символьном виде:
SET ˽ #1.5 ˽0˽0˽1\r\n1\r\n
GET ˽ #1.5 \r\n вернет символ “1” – 1 байт
GET ˽ 1.5 \r\n вернет int32: 0x1 – 4 байта
SET ˽ 1.5 ˽0˽0˽1\r\n1\r\n
GET ˽ 1.5 \r\n вернет int32: 0x31
Пригодится в отладке типа index
dev.it-portfolio.net 54
чистка мусора (garbage collector)
dev.it-portfolio.net 55
Удаленные профили нужно удалять из хранилища Требуется перебор всех данных Делается, блоками, когда процессор наименее загружен Вычисляем загрузку сервиса, Подбираем опытным путем.
Проблемы
dev.it-portfolio.net 56
- Удаленные профили надо чистить
- Постоянно растет память, нужно сбрасывать кеш, переоткрывать таблицы
- Вывод: Необходим мониторинг
Мониторинг
- Настраиваем rdd
- Рисуем графики
dev.it-portfolio.net 57
- Команда stats
Мониторинг
dev.it-portfolio.net 58
- Память из /proc/self/stat
- Производительность: кол-во запросов в сек
- Загрузка: отношение времени исполнения к циклу измерения
- Размер корзины
- Общее кол-во ключей
Мониторинг
dev.it-portfolio.net 59
Тестирование
dev.it-portfolio.net 60
API покрыли тестами Схх http://cxxtest.com Тестирование производительности: aналог Apache ab, протокол memcached https://github.com/akalend/mcstrass
Используемые Библиотеки
dev.it-portfolio.net 61
libev – сетевая однотредовая модель libtokyocabinet – hashdb & treedb tcmalloc - Memory pool allocator
Рекомендуемые Библиотеки
dev.it-portfolio.net 62
Сетевые: libevent2 http://libevent.org/ libev http://software.schmorp.de/pkg/libev.html
Коротины: libcoro http://software.schmorp.de/pkg/libcoro.html
pcl http://xmailserver.org/libpcl.html
libtask http://swtch.com/libtask/
Рекомендуемые Библиотеки
dev.it-portfolio.net 63
Хештаблицы: Tokyo/Kyoto http://fallabs.com/ [cabinet] libdict https://github.com/fmela/libdic strmap http://pokristensson.com/strmap.html sglib http://sglib.sourceforge.net/ Judy http://judy.sourceforge.net/ levelDb http://code.google.com/p/leveldb/ Sophia http://sphia.org/ uthash http://troydhanson.github.io/uthash/index.html
sunriseDb http://www.sunrisetel.net/software/devtools/sunrise-data-
dictionary.shtml
Рекомендуем почитать
dev.it-portfolio.net 64
Блог о высоких нагрузках http://highloadblog.ru/
http://ru.wikipedia.org/wiki/Хеш-таблица http://ru.wikipedia.org/wiki/B-дерево
Алгоритмы и структуры http://algolist.ru/
Опыт создания key/value хранилищ СА сент,окт,нояб,дек 2012, март 2013.
Вопросы
dev.it-portfolio.net 65
Q: Open Source ?
A: в полной версии нет, не вижу смысла
есть прототип, который можно заточить под
любые нужды вашего проекта
https://github.com/akalend/mymc