MongoDB is a web-scale
Курс «Базы данных»
Антон Волохов
Yandex

7 октября 2013 г.

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

1 / 51
Содержание
1

Введение

2

API

3

Storage internals

4

Replication

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

2 / 51
Содержание

5

Sharding

6

Секретный ингредиент

7

Заключение

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

3 / 51
Введение

Терминология

Терминология
Документ - Ряд в RDBMS
Коллекция - Таблица в RDBMS
База данных - Базы данных в MySql
Пространство имён - Пара <база данных,
коллекция>
Нода - Процесс базы данных, осуществляющий
хранение и поиск пользовательских данных на
диске
Реплика - Множество Node, обладающее
полной копией одних и тех же данных
Шард - Единица масштабирования БД
А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

4 / 51
Введение

Disclaimer

Disclaimer

Если есть вопрос, меня можно и нужно перебивать
Не на каждый вопрос я смогу ответить по ходу
лекции
Не на каждый вопрос я смогу ответить

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

5 / 51
API

Декларированные цели

Декларированные цели

Производительность
Простота использования
Горизонтальное масштабирование
Обработка эволюционирующих данных
Конкуренция с RDBMS

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

6 / 51
API

MongoDB features

MongoDB features

BSON протокол
JS консоль
Хранимые процедуры
Master-slave репликация
Шардирование без даунтайма
Система хранения файлов GridFS

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

7 / 51
API

MongoDB features

API
Хранимые процедуры
> db . system . js . insert ({ " _id " : " inc " , " value " : f u n c t i o n ( x )
{ r e t u r n x +1}})
> db . eval ( " inc (1) " )
2

Индексы
MapReduce
Уникальный первичный ключ
> db.books.insert({foo:"bar"})
> db.books.find()
{ "_id" : ObjectId("5251664b629201a4d4164ec0"), "foo" : "bar" }

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

8 / 51
API

Querying

Примеры запросов
Документы
isbn = {
_id: "0-321-34960-1",
author: "B. Goetz",
title: "Java Concurrency In Practice",
ISBN :{
"ISBN-10": "0-321-34960-1",
"ISBN-13": "978-0-321-34960-6"
},
"authors-list":["Brian Goetz", "Tim Peierls", "Doug Lea", "Joseph
Bowbeer", "David Holmes"]
}

Запросы
db.test.insert(isbn)
db.test.find({ "title"
db.test.update(isbn, {
db.test.insert({ "foo"
db.test.find({ "title"
}})

А. В. Волохов (Yandex)

: /Java/ })
$push : { "authors-list" : "Joshua Bloch" }})
: "bar" })
: { $gte : "Java" }, "title" : { $lt : "Python"

MongoDB

7 октября 2013 г.

9 / 51
API

Querying

Вложенные документы
> db.items.insert({ foo : "foo", "bar" : { "first" : 1, "second" : 1 }})
> db.items.insert({ foo : "foo", "bar" : { "first" : 1, "second" : 2 }})
> db.items.insert({ foo : "foo", "bar" : { "first" : 2, "second" : 1 }})

Запрос на точное совпадение
> db.items.find({ bar:{ "first" : 1 , "second" : 1 }})
{ "_id" : ObjectId("52517090629201a4d4164ec1"), "foo" : "foo",
"bar" : { "first" : 1, "second" : 1 } }

Запрос на диапазон значений
> db.items.find({ bar : { $gte : { "first" : 1, "second" : "" }},
"bar" : { $lt : { "first" : 2, "second" : "" }}})
{ "_id" : ObjectId("52517090629201a4d4164ec1"), "foo" : "foo",
"bar" : { "first" : 1, "second" : 1 } }
{ "_id" : ObjectId("5251709e629201a4d4164ec2"), "foo" : "foo",
"bar" : { "first" : 1, "second" : 2 } }

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

10 / 51
Storage internals

Работа с файловой системой

Работа с файловой системой
Аллокейтим файлы на диске отдельно для каждой
базы данных
-rw-------rw-------rw------...
-rw-------rw-------

1 mongodb nogroup 16M test.ns
1 mongodb nogroup 64M test.0
1 mongodb nogroup 128M test.1
1 mongodb nogroup 2.0G test.5
1 mongodb nogroup 2.0G test.6

Создаём служебную базу данных (∼ 5% дискового
пространства)

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

11 / 51
Storage internals

Работа с файловой системой

Кеширование

Не in-memory database
Не занимаемся memory management
Memory-mapped files
File system cache

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

12 / 51
Storage internals

Работа с файловой системой

Файлы данных
Экстент
Указатели на первую и последнюю запись
Положение
Длина
Пространство имён

Запись
Длина
Смещение внутри экстента
Смещения предыдущей и последующей записей
Документ
Padding

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

13 / 51
Storage internals

Advanced querying

В свете этого
Удаление
Помечаем пространство как свободное
Не пишем на диск
Добавление
Лениво
В первый найденный свободный блок
Обновление
Документ увеличился?
Влезает ли обновлённый элемент в свой блок?
А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

14 / 51
Storage internals

Advanced querying

Администрирование
Проблемы
1
Фрагментация данных
2
Параллельное изменение одних и тех же файлов
3
Неконтролируемое разрастание файлов данных
Решения
1
compact
2
глобальные блокировки на уровне базы данных
3
repair базы
Резюме
Ни одного адекватного решения
А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

15 / 51
Storage internals

Advanced querying

Пространство имён

Индексы
Коллекции
Экстенты
Статистика

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

16 / 51
Storage internals

Индексы

Индексы

B-Дерево
Композитный индекс
По массиву и поддокументу
Запоминаем оптимальный план запроса
.explain()

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

17 / 51
Replication

Replication

Master - Slave

Запись только на одну машину
Чтение со всех машин
Настраиваемая консистентность
А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

18 / 51
Replication

Replication

Консистентность
Не проверяем, удалась ли запись
Ошибки записи в текущем соединении
getLastError()
Ждёт, когда W машин запишут все изменения в
текущем соединении с момента предыдущего
getLastError()
По-сути, точка синхронизации
Не верьте бенчмаркам!
Если не вызывать getLastError(), клиент будет писать в
монгу, не зная, прошла ли запись. Результат - over9000
rps, при неопределённом числе удачных записей.
А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

19 / 51
Replication

Replication

Replication internals

Лог операций
Простейшие преобразования запросов
Транзитивность репликации
Текущий мастер выбирается голосованием

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

20 / 51
Replication

Replication

Replication internals: oplog polling

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

21 / 51
Replication

Replication

Replication internals: voting
Все машины реплики знают друг о друге
Мастер пингует все машины своей реплики
Если мастер не видит кворум, он снимает с себя
полномочия
Процесс голосования инициирует машина,
которая не может найти мастера
Голосование начинается в случае, если мастер не
виден кворумом

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

22 / 51
Replication

Replication

Replication internals: Rollback and
Recovery
1

2

Откатываются все изменения, которых нет на
мастере
Накатываются все изменения нового мастера

NB!
Нет автоматического разрешения конфликтов
Нет внятного оповещения о существовании
конфликтов

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

23 / 51
Sharding

Overview

Overview

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

24 / 51
Sharding

Overview

Overview

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

25 / 51
Sharding

Sharding meta

Sharding meta

Точечные запросы по шардам
Автоматическая балансировка
Локализация данных

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

26 / 51
Sharding

Sharding meta

Sharding meta
А что внутри?
Где хранить метаданные?
Как обеспечить надёжность?
Как сгруппировать данные для шардирования?

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

27 / 51
Sharding

Sharding meta

Configuration Server

Нет репликации
Синхронная запись
Two phase commit
Read-Only при отказе одной из машин

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

28 / 51
Sharding

Sharding in a Nutshell

Шардируем

1
2

Объявляем коллекцию как шардированную
Выбираем поле, по которому будут строится чанки

Чанк
Начало диапазона
Конец диапазона
Объем
Принадлежность к шарду

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

29 / 51
Sharding

Sharding in a Nutshell

Балансируем
Периодичный бэкграунд процесс роутера
Workflow
1
Пытаемся взять lock
2
Если удалось, опрашиваем каждое пространство
имён
3
Смотрим на распределение и заполненность
чанков
4
Определяем, нужно ли делить или перемещать
чанки
5
Осуществляем миграцию
А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

30 / 51
Sharding

Sharding in a Nutshell

Решаем проблемы
Плохо
Ходить на каждый запрос в амстердам с западного
побережья - не комильфо.
Кеширование на стороне роутера
Всё ещё плохо
После каждой миграции, кешированная информация
становится протухшей.
Оповещаем роутеры, они обновляют кеш
На хлеб уже мажется.
А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

31 / 51
Sharding

Sharding in a Nutshell

Решаем проблемы
Но ещё пахнет
Не можем контролировать распределение чанков; нет
заявленной локализации данных
Тэги
Свойство шарда
Отображение из диапазона ключей в тэг

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

32 / 51
Sharding

Sharding in a Nutshell

Тэги
{ ns : "test.books", minKey : { date : 01.01.2013 }, maxKey : {date : $MaxKey
}, tag : "ssd" }

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

33 / 51
Sharding

Sharding in a Nutshell

Не решаем проблем
Не предусмотренное
DDL-убивашка
Нельзя так просто взять и поменять ключ
шардирования
Если поздно объявить коллекцию шардированной,
все существующие данные навсегда окажутся в
одном чанке
Чанки не умеют склеиваться и не умирают при
опустении

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

34 / 51
Sharding

Ключ шардирования

Выбираем ключ шардирования
Схема:
100 000 000 записей
{url: "http://www.imdb.com/title/tt0795176/", domain : 1, title:
"Planet Earth", "air date": 2007, seasons:[1], rating:9.5
cast:<...>, similar:<...>, description:<...> }

Полный урл уникален
Некоторые домены могут содержать десятки тысяч
документов
Список доменов меняется редко, информация по урлам
меняется часто, домены имеют возрастающий
идентификатор
Запросы
Достать одну сущность по урлу
Достать 1000 сущностей по урлам
Достать всё из www.imdb.com
Отгрузить всю базу
А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

35 / 51
Sharding

Ключ шардирования

Выборы ключа шардирования (0)

Возможные варианты
ObjectId()
Поле с рандомным значением
Урл
Хеш от урла
Пара <хеш от домена, хеш от урла>

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

36 / 51
Sharding

Ключ шардирования

Выборы ключа шардирования (1)
ObjectId
Преимущества
Монотонно возрастает - легко собрать чанк
Недостатки
Монотонно возрастает - запись в один шард
Монотонно возрастает - пустые чанки
Невозможно поддержать уникальность урлов в
разных шардах

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

37 / 51
Sharding

Ключ шардирования

Выборы ключа шардирования (2)
Случайное значение
Преимущества
Равномерная распределённость - запись во все
шарды
Равномерная распределённость - нет пустых
чанков
Недостатки
Равномерная распределённость - очень долгая
миграция, стынет кеш
Невозможно поддержать уникальность урлов в
разных шардах
А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

38 / 51
Sharding

Ключ шардирования

Выборы ключа шардирования (3)
Урл
Преимущества
Уникальность урлов
Локализация запросов
Запись во все шарды
Мало пустых чанков
Недостатки
Тяжеловесный индекс
Сложно собрать чанк - долгая миграция чанка
А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

39 / 51
Sharding

Ключ шардирования

Выборы ключа шардирования (4)
Пара id домена- хеш от урла
Преимущества
Те же, что и от урла
Плюс бесплатный индекс по домену
Быстрая миграция, если обновления по домену
приходят батчами
Легковесный индекс
Недостатки
Долгая миграция, если гипотеза о батчах неверна
Иногда чанки пустеют
А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

40 / 51
Sharding

Ключ шардирования

Выборы ключа шардирования (5)

Резюме
На какие запросы хотим отвечать?
Монотонно возрастающий ключ - плохо
Полностью рандомный ключ - плохо
Шардовый ключ участвует в запросе дополнительный профит

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

41 / 51
Sharding

Ключ шардирования

Выборы ключа шардирования. Итоги
Студент! Помни!

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

42 / 51
Секретный ингредиент

Почему MongoDB не production-ready?

Почему MongoDB не production-ready?

Писалась исходя из того, что она работает
Только SocketException в логах
Совершенно не описано поведение в
неблагоприятных условиях
Некачественные мониторинги

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

43 / 51
Секретный ингредиент

Почему MongoDB не production-ready?

Кстати о мониторингах
db.serverStatus()
Возвращает кучу данных о базе
Все показатели - в миллисекундах от старта сервера
Мониторинг дёргает serverStatus
А теперь представим, что система перегружена
1
Дёргаем serverStatus
2
Через 20 секунд получаем ответ
3
Через минуту дёргаем ещё раз
4
Через 20 секунд получаем ответ
5
Разность значений может быть статистикой за любой
промежуток времени от 40 до 80 секунд
А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

44 / 51
Секретный ингредиент

Почему MongoDB не production-ready?

Кстати о мониторингах
А теперь делим разность из предыдущего слайда на 60
И получается, что за последнюю минуту половина баз
была заблокирована на чтение в течение не меньше
чем 90 секунд.
Не вся статистика разделена по пространствам
имён
Не знаем, какие именно запросы перегружают
базу

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

45 / 51
Секретный ингредиент

Почему MongoDB не production-ready?

WAT?

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

46 / 51
Секретный ингредиент

Эксплуатация

Если действительно нужен функционал
1
2
3
4

5
6
7

Предельно уяснить, какие запросы важные
Описать ограничения уникальности
Построить ключ шардирования
Не выполнять DDL на боевых базах без крайней
необходимости
Всегда вручную передёргивать роутеры после DDL
Заблаговременно масштабировать
Не тянуть с шардированием

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

47 / 51
Заключение

Сухой остаток

Сухой остаток
Почему MongoDB - это действительно круто
Однокнопочные шардирование и репликация
Богатый язык запросов
Вторичные индексы
Почему нужно трижды подумать
Нечитаемые логи
Непонятно, где у монги болит
При неосторожном обращении, легко превратить
всё в тыкву
Не жмутся названия полей
А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

48 / 51
Заключение

Осталось за кадром

Осталось за кадром
http://www.kchodorow.com/blog/2010/08/23/
history-of-mongodb/ - История создания
продукта
Авторизация
GridFS
Профилирование
Aggregation framework
MapReduce

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

49 / 51
Заключение

Осталось за кадром

Литература

http://www.amazon.com/
MongoDB-Definitive-Guide-Kristina-Chodorow/
dp/1449344682
http://docs.mongodb.org/manual/
http://www.kchodorow.com/blog/index.php?s=
mongodb

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

50 / 51
Вопросы?

Вопросы?

Почта a.v.volokhov@gmail.com

А. В. Волохов (Yandex)

MongoDB

7 октября 2013 г.

51 / 51

Базы данных. MongoDB

  • 1.
    MongoDB is aweb-scale Курс «Базы данных» Антон Волохов Yandex 7 октября 2013 г. А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 1 / 51
  • 2.
    Содержание 1 Введение 2 API 3 Storage internals 4 Replication А. В.Волохов (Yandex) MongoDB 7 октября 2013 г. 2 / 51
  • 3.
  • 4.
    Введение Терминология Терминология Документ - Рядв RDBMS Коллекция - Таблица в RDBMS База данных - Базы данных в MySql Пространство имён - Пара <база данных, коллекция> Нода - Процесс базы данных, осуществляющий хранение и поиск пользовательских данных на диске Реплика - Множество Node, обладающее полной копией одних и тех же данных Шард - Единица масштабирования БД А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 4 / 51
  • 5.
    Введение Disclaimer Disclaimer Если есть вопрос,меня можно и нужно перебивать Не на каждый вопрос я смогу ответить по ходу лекции Не на каждый вопрос я смогу ответить А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 5 / 51
  • 6.
    API Декларированные цели Декларированные цели Производительность Простотаиспользования Горизонтальное масштабирование Обработка эволюционирующих данных Конкуренция с RDBMS А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 6 / 51
  • 7.
    API MongoDB features MongoDB features BSONпротокол JS консоль Хранимые процедуры Master-slave репликация Шардирование без даунтайма Система хранения файлов GridFS А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 7 / 51
  • 8.
    API MongoDB features API Хранимые процедуры >db . system . js . insert ({ " _id " : " inc " , " value " : f u n c t i o n ( x ) { r e t u r n x +1}}) > db . eval ( " inc (1) " ) 2 Индексы MapReduce Уникальный первичный ключ > db.books.insert({foo:"bar"}) > db.books.find() { "_id" : ObjectId("5251664b629201a4d4164ec0"), "foo" : "bar" } А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 8 / 51
  • 9.
    API Querying Примеры запросов Документы isbn ={ _id: "0-321-34960-1", author: "B. Goetz", title: "Java Concurrency In Practice", ISBN :{ "ISBN-10": "0-321-34960-1", "ISBN-13": "978-0-321-34960-6" }, "authors-list":["Brian Goetz", "Tim Peierls", "Doug Lea", "Joseph Bowbeer", "David Holmes"] } Запросы db.test.insert(isbn) db.test.find({ "title" db.test.update(isbn, { db.test.insert({ "foo" db.test.find({ "title" }}) А. В. Волохов (Yandex) : /Java/ }) $push : { "authors-list" : "Joshua Bloch" }}) : "bar" }) : { $gte : "Java" }, "title" : { $lt : "Python" MongoDB 7 октября 2013 г. 9 / 51
  • 10.
    API Querying Вложенные документы > db.items.insert({foo : "foo", "bar" : { "first" : 1, "second" : 1 }}) > db.items.insert({ foo : "foo", "bar" : { "first" : 1, "second" : 2 }}) > db.items.insert({ foo : "foo", "bar" : { "first" : 2, "second" : 1 }}) Запрос на точное совпадение > db.items.find({ bar:{ "first" : 1 , "second" : 1 }}) { "_id" : ObjectId("52517090629201a4d4164ec1"), "foo" : "foo", "bar" : { "first" : 1, "second" : 1 } } Запрос на диапазон значений > db.items.find({ bar : { $gte : { "first" : 1, "second" : "" }}, "bar" : { $lt : { "first" : 2, "second" : "" }}}) { "_id" : ObjectId("52517090629201a4d4164ec1"), "foo" : "foo", "bar" : { "first" : 1, "second" : 1 } } { "_id" : ObjectId("5251709e629201a4d4164ec2"), "foo" : "foo", "bar" : { "first" : 1, "second" : 2 } } А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 10 / 51
  • 11.
    Storage internals Работа сфайловой системой Работа с файловой системой Аллокейтим файлы на диске отдельно для каждой базы данных -rw-------rw-------rw------... -rw-------rw------- 1 mongodb nogroup 16M test.ns 1 mongodb nogroup 64M test.0 1 mongodb nogroup 128M test.1 1 mongodb nogroup 2.0G test.5 1 mongodb nogroup 2.0G test.6 Создаём служебную базу данных (∼ 5% дискового пространства) А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 11 / 51
  • 12.
    Storage internals Работа сфайловой системой Кеширование Не in-memory database Не занимаемся memory management Memory-mapped files File system cache А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 12 / 51
  • 13.
    Storage internals Работа сфайловой системой Файлы данных Экстент Указатели на первую и последнюю запись Положение Длина Пространство имён Запись Длина Смещение внутри экстента Смещения предыдущей и последующей записей Документ Padding А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 13 / 51
  • 14.
    Storage internals Advanced querying Всвете этого Удаление Помечаем пространство как свободное Не пишем на диск Добавление Лениво В первый найденный свободный блок Обновление Документ увеличился? Влезает ли обновлённый элемент в свой блок? А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 14 / 51
  • 15.
    Storage internals Advanced querying Администрирование Проблемы 1 Фрагментацияданных 2 Параллельное изменение одних и тех же файлов 3 Неконтролируемое разрастание файлов данных Решения 1 compact 2 глобальные блокировки на уровне базы данных 3 repair базы Резюме Ни одного адекватного решения А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 15 / 51
  • 16.
    Storage internals Advanced querying Пространствоимён Индексы Коллекции Экстенты Статистика А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 16 / 51
  • 17.
    Storage internals Индексы Индексы B-Дерево Композитный индекс Помассиву и поддокументу Запоминаем оптимальный план запроса .explain() А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 17 / 51
  • 18.
    Replication Replication Master - Slave Записьтолько на одну машину Чтение со всех машин Настраиваемая консистентность А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 18 / 51
  • 19.
    Replication Replication Консистентность Не проверяем, удаласьли запись Ошибки записи в текущем соединении getLastError() Ждёт, когда W машин запишут все изменения в текущем соединении с момента предыдущего getLastError() По-сути, точка синхронизации Не верьте бенчмаркам! Если не вызывать getLastError(), клиент будет писать в монгу, не зная, прошла ли запись. Результат - over9000 rps, при неопределённом числе удачных записей. А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 19 / 51
  • 20.
    Replication Replication Replication internals Лог операций Простейшиепреобразования запросов Транзитивность репликации Текущий мастер выбирается голосованием А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 20 / 51
  • 21.
    Replication Replication Replication internals: oplogpolling А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 21 / 51
  • 22.
    Replication Replication Replication internals: voting Всемашины реплики знают друг о друге Мастер пингует все машины своей реплики Если мастер не видит кворум, он снимает с себя полномочия Процесс голосования инициирует машина, которая не может найти мастера Голосование начинается в случае, если мастер не виден кворумом А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 22 / 51
  • 23.
    Replication Replication Replication internals: Rollbackand Recovery 1 2 Откатываются все изменения, которых нет на мастере Накатываются все изменения нового мастера NB! Нет автоматического разрешения конфликтов Нет внятного оповещения о существовании конфликтов А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 23 / 51
  • 24.
    Sharding Overview Overview А. В. Волохов(Yandex) MongoDB 7 октября 2013 г. 24 / 51
  • 25.
    Sharding Overview Overview А. В. Волохов(Yandex) MongoDB 7 октября 2013 г. 25 / 51
  • 26.
    Sharding Sharding meta Sharding meta Точечныезапросы по шардам Автоматическая балансировка Локализация данных А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 26 / 51
  • 27.
    Sharding Sharding meta Sharding meta Ачто внутри? Где хранить метаданные? Как обеспечить надёжность? Как сгруппировать данные для шардирования? А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 27 / 51
  • 28.
    Sharding Sharding meta Configuration Server Нетрепликации Синхронная запись Two phase commit Read-Only при отказе одной из машин А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 28 / 51
  • 29.
    Sharding Sharding in aNutshell Шардируем 1 2 Объявляем коллекцию как шардированную Выбираем поле, по которому будут строится чанки Чанк Начало диапазона Конец диапазона Объем Принадлежность к шарду А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 29 / 51
  • 30.
    Sharding Sharding in aNutshell Балансируем Периодичный бэкграунд процесс роутера Workflow 1 Пытаемся взять lock 2 Если удалось, опрашиваем каждое пространство имён 3 Смотрим на распределение и заполненность чанков 4 Определяем, нужно ли делить или перемещать чанки 5 Осуществляем миграцию А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 30 / 51
  • 31.
    Sharding Sharding in aNutshell Решаем проблемы Плохо Ходить на каждый запрос в амстердам с западного побережья - не комильфо. Кеширование на стороне роутера Всё ещё плохо После каждой миграции, кешированная информация становится протухшей. Оповещаем роутеры, они обновляют кеш На хлеб уже мажется. А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 31 / 51
  • 32.
    Sharding Sharding in aNutshell Решаем проблемы Но ещё пахнет Не можем контролировать распределение чанков; нет заявленной локализации данных Тэги Свойство шарда Отображение из диапазона ключей в тэг А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 32 / 51
  • 33.
    Sharding Sharding in aNutshell Тэги { ns : "test.books", minKey : { date : 01.01.2013 }, maxKey : {date : $MaxKey }, tag : "ssd" } А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 33 / 51
  • 34.
    Sharding Sharding in aNutshell Не решаем проблем Не предусмотренное DDL-убивашка Нельзя так просто взять и поменять ключ шардирования Если поздно объявить коллекцию шардированной, все существующие данные навсегда окажутся в одном чанке Чанки не умеют склеиваться и не умирают при опустении А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 34 / 51
  • 35.
    Sharding Ключ шардирования Выбираем ключшардирования Схема: 100 000 000 записей {url: "http://www.imdb.com/title/tt0795176/", domain : 1, title: "Planet Earth", "air date": 2007, seasons:[1], rating:9.5 cast:<...>, similar:<...>, description:<...> } Полный урл уникален Некоторые домены могут содержать десятки тысяч документов Список доменов меняется редко, информация по урлам меняется часто, домены имеют возрастающий идентификатор Запросы Достать одну сущность по урлу Достать 1000 сущностей по урлам Достать всё из www.imdb.com Отгрузить всю базу А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 35 / 51
  • 36.
    Sharding Ключ шардирования Выборы ключашардирования (0) Возможные варианты ObjectId() Поле с рандомным значением Урл Хеш от урла Пара <хеш от домена, хеш от урла> А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 36 / 51
  • 37.
    Sharding Ключ шардирования Выборы ключашардирования (1) ObjectId Преимущества Монотонно возрастает - легко собрать чанк Недостатки Монотонно возрастает - запись в один шард Монотонно возрастает - пустые чанки Невозможно поддержать уникальность урлов в разных шардах А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 37 / 51
  • 38.
    Sharding Ключ шардирования Выборы ключашардирования (2) Случайное значение Преимущества Равномерная распределённость - запись во все шарды Равномерная распределённость - нет пустых чанков Недостатки Равномерная распределённость - очень долгая миграция, стынет кеш Невозможно поддержать уникальность урлов в разных шардах А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 38 / 51
  • 39.
    Sharding Ключ шардирования Выборы ключашардирования (3) Урл Преимущества Уникальность урлов Локализация запросов Запись во все шарды Мало пустых чанков Недостатки Тяжеловесный индекс Сложно собрать чанк - долгая миграция чанка А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 39 / 51
  • 40.
    Sharding Ключ шардирования Выборы ключашардирования (4) Пара id домена- хеш от урла Преимущества Те же, что и от урла Плюс бесплатный индекс по домену Быстрая миграция, если обновления по домену приходят батчами Легковесный индекс Недостатки Долгая миграция, если гипотеза о батчах неверна Иногда чанки пустеют А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 40 / 51
  • 41.
    Sharding Ключ шардирования Выборы ключашардирования (5) Резюме На какие запросы хотим отвечать? Монотонно возрастающий ключ - плохо Полностью рандомный ключ - плохо Шардовый ключ участвует в запросе дополнительный профит А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 41 / 51
  • 42.
    Sharding Ключ шардирования Выборы ключашардирования. Итоги Студент! Помни! А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 42 / 51
  • 43.
    Секретный ингредиент Почему MongoDBне production-ready? Почему MongoDB не production-ready? Писалась исходя из того, что она работает Только SocketException в логах Совершенно не описано поведение в неблагоприятных условиях Некачественные мониторинги А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 43 / 51
  • 44.
    Секретный ингредиент Почему MongoDBне production-ready? Кстати о мониторингах db.serverStatus() Возвращает кучу данных о базе Все показатели - в миллисекундах от старта сервера Мониторинг дёргает serverStatus А теперь представим, что система перегружена 1 Дёргаем serverStatus 2 Через 20 секунд получаем ответ 3 Через минуту дёргаем ещё раз 4 Через 20 секунд получаем ответ 5 Разность значений может быть статистикой за любой промежуток времени от 40 до 80 секунд А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 44 / 51
  • 45.
    Секретный ингредиент Почему MongoDBне production-ready? Кстати о мониторингах А теперь делим разность из предыдущего слайда на 60 И получается, что за последнюю минуту половина баз была заблокирована на чтение в течение не меньше чем 90 секунд. Не вся статистика разделена по пространствам имён Не знаем, какие именно запросы перегружают базу А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 45 / 51
  • 46.
    Секретный ингредиент Почему MongoDBне production-ready? WAT? А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 46 / 51
  • 47.
    Секретный ингредиент Эксплуатация Если действительнонужен функционал 1 2 3 4 5 6 7 Предельно уяснить, какие запросы важные Описать ограничения уникальности Построить ключ шардирования Не выполнять DDL на боевых базах без крайней необходимости Всегда вручную передёргивать роутеры после DDL Заблаговременно масштабировать Не тянуть с шардированием А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 47 / 51
  • 48.
    Заключение Сухой остаток Сухой остаток ПочемуMongoDB - это действительно круто Однокнопочные шардирование и репликация Богатый язык запросов Вторичные индексы Почему нужно трижды подумать Нечитаемые логи Непонятно, где у монги болит При неосторожном обращении, легко превратить всё в тыкву Не жмутся названия полей А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 48 / 51
  • 49.
    Заключение Осталось за кадром Осталосьза кадром http://www.kchodorow.com/blog/2010/08/23/ history-of-mongodb/ - История создания продукта Авторизация GridFS Профилирование Aggregation framework MapReduce А. В. Волохов (Yandex) MongoDB 7 октября 2013 г. 49 / 51
  • 50.
  • 51.
    Вопросы? Вопросы? Почта a.v.volokhov@gmail.com А. В.Волохов (Yandex) MongoDB 7 октября 2013 г. 51 / 51