Введение Коллеги, при разработке приложений мы каждый день сталкиваемся с необходимостью гибкого хранения информации (обновление, поиск и т.п.
).
Класс продуктов, решающих этот круг задач, как мы все знаем, — это базы данных.
Но что это такое в нашем понимании? Многие люди ассоциируют «базу данных» с MySQL, таблицами и запросами SQL. И это меня устраивает до определенного момента.
Действительно, реляционные базы данных дают массу эксплуатационных преимуществ: поскольку данные тесно связаны, нет необходимости следить за целостностью базы данных.
Используя простой подзапрос, вы можете выбрать количество комментариев для каждого сообщения в блоге.
Используя JOIN, можно легко выполнять сложные связанные выборки и получать данные о нескольких объектах одновременно.
Масштабировал-масштабировал, но не масштабировал
Однако когда вы вдруг понимаете, что одного сервера уже недостаточно, и вы хотите разнести базу данных по нескольким физическим машинам, первое, что предлагается — репликация master-slave, при которой запись идет на одну машину, а чтение — на несколько.Но при достаточно большом количестве изменений вскоре мастер ничего не будет делать, кроме как раздавать логи, и вам придется прибегнуть к сложной настройке, чтобы каждый узел имел один покровительствующий сервер (мастер) и мог иметь несколько подчиненных серверов.
Данная схема очень сложна в реализации и содержит единственную точку отказа (т.е.
при выходе из строя одного сервера все его подчиненные быстро превращаются в динозавров).
Опять же, все эти уловки только увеличат количество прочтений.
А если мощности одного сервера недостаточно для внесения изменений в состояние базы данных, то приходится распределять нагрузку, храня разные таблицы на разных серверах.
Но тогда связь потеряется.
Либо придётся разбивать таблицу на несколько частей, сохраняя их в разных местах, по заданному закону (например, по ID), но это унесёт прелести JOIN в могилу.
Чем дальше мы пытаемся масштабировать реляционные базы данных, тем больше удобства мы платим за это.
Например, при использовании мастер-мастер мы будем платить с автоматическим приращением.
Спасут ли нас MemcacheDB и Redis?
Подобные решения «ключ-значение» существуют уже довольно давно.На мой взгляд, MemcacheDB — это хак, паразитирующий на добром имени замечательного продукта: данные там абсолютно не связаны друг с другом, мы можем выполнять операции только над значением, зная ключ.
Я потратил много времени на написание инструментов, позволяющих мне выгодно работать с базами данных типа MemcacheDB, и это даже работает, но я пришёл к выводу, что простые бытовые задачи решаются настолько криво, что невольно думаешь в сторону реляционализма.
: например, нет даже элементарной реализации времени жизни объекта времени (TTL), т.е.
нельзя брать и удалять сессии старше месяца.
Это не приносит результатов.
Авторы Redis пошли в своих извращенных фантазиях чуть дальше и сделали атомарные списки и наборы ключей, но особых успехов в облегчении жизни программисту не добились.
Более того, вам все равно придется вручную поддерживать кэш ключей, т.е.
сохранять нужные ключи в Memcached и брать их из него, что создает массу проблем с синхронизацией.
При этом атомарности операций тоже нет: возникает гонка между получением объекта и записью его в кэш, CAS демотивирует нас своей производительностью.
Что делать, если мы хотим каталог товаров, похожий на Яндекс.
Маркет? Допустим, мы хотим сделать каталог, в котором поиск осуществляется по таким параметрам, как цена, рейтинг, коэффициент масштабирования камеры и количество передач на велосипеде.
Допустим, мы используем реляционную базу данных, например MySQL. Что нам делать? Мы должны либо создать таблицу товаров, в которой будет содержаться и коэффициент масштабирования, и количество передач для велосипеда, и, например, показатель гибкости щетины зубной щетки (в этом случае мы упремся в поле ограничение для таблицы, иначе мы потеряем дисковое пространство, скорость и удобство), или нам следует создать таблицу типа Good_id, Key, Value и делать ужасные JOINы для выборки и поиска, не заморачиваясь о масштабировании.
Вы также можете использовать для этого Sphinx или что-то похуже, но это, скорее всего, будет похоже на забивание гвоздей ноутбуком.
У родственных женщин серьезная родовая травма.
MongoDB, говоришь?
МонгоБД - объектно-документная база данных острая как понос.Идеологически это своего рода симбиоз обычной реляционной базы данных и хранилища «ключ-значение», и, на мой взгляд, весьма удачный.
С одной стороны, он позволяет совершать очень быстрые операции над объектом, зная его идентификатор, а с другой стороны, предоставляет мощный инструмент для сложных взаимодействий.
Коллекция — это именованный набор объектов, в котором один объект принадлежит только одной коллекции.
Объект представляет собой набор свойств, включая уникальный идентификатор _id. Свойство представляет собой комбинацию имени и соответствующего ему типа и значения.
Типы свойств — строка, целое число, число с плавающей запятой, массив, объект, двоичная строка, байт, символ, дата, логическое значение, ноль.
Поддерживаются операции выбора (подсчет, группа, MapReduce.), вставка, изменение и удаление.
Между объектами нет связей; объекты могут хранить другие объекты только в свойствах.
Поддерживаются как уникальные, так и составные индексы.
Индексы можно размещать в свойствах вложенных объектов.
Поддерживается репликация (даже подразумеваемая), реализован отказоустойчивость.
Реализован MapReduce и шардинг.
Поскольку объекты могут иметь произвольный набор свойств, для каталога достаточно создать коллекцию товаров и поместить туда объекты.
В этом случае поиск будет осуществляться по индексам.
Острота MongoDB ярко выражена во вставках, они происходят очень быстро.
Кстати, приятно, что формат хранения и формат передачи объектов по сети одинаковы, поэтому для выбора объекта достаточно найти его позицию по индексу и вернуть в файл кусок файла определенной длины.
клиент — никакой абстракции над механизмом хранения.
Уникальный идентификатор — это не поле с автоинкрементом, а 12-байтовое уникальное число, сгенерированное на клиенте.
Таким образом, во-первых, нет проблем с синхронизацией реплик, т.е.
вы можете независимо делать вставки на двух разных машинах, и конфликта не будет. Во-вторых, не будет глупостей с целочисленным переполнением, и после пересоздания базы поисковые системы не будут ссылаться на новые статьи по старым ссылкам.
MongoDB + Memcached? Круче Бонни и Клайда!
С базой данных мы более-менее разобрались, теперь давайте подумаем, как можно все это дело закешировать, ведь мы хотим раздавать горячие пирожки на скорости Memcached! Во-первых, кэширование самих объектов.Как многие догадались или узнали из опыта, в большинстве случаев операция выбора объекта по ID является самой распространенной.
Например, выбор объекта пользователя, выбор данного поста из базы Хабрахабра (аминь) и т.д. Как мы уже выяснили выше, перекладывать эту работу на приложение неразумно, ведь пришлось бы городить огород распределенных блокировок.
Пойдем другим путем, напишем асинхронное приложение, которое будет подключаться к MongoDB и, прикидываясь слейвом, будет получать лог изменений и сбрасывать изменения в Memcached (если объект содержит ключ в свойстве _key).
Поскольку приложение асинхронное, это произойдет быстро, но состояния гонки не возникнет. Написать легко, моя реализация здесь .
Более того, я добавил туда еще и отправку изменений на сервер событий, так что мне нужно всего лишь изменить объект откуда угодно (или даже из консоли), и он сразу же будет передан всем подписанным на него клиентам.
Кэширование запросов и аннулирование кеша должны работать немного по-другому.
Существует несколько подходов:
- Кэш на определенное время.
Если запросы одинаковые или их немного, то обновлять кэш можно не чаще одного раза в секунду — это значительно снизит нагрузку.
- Удаление кэша по запросу приложения.
Подход довольно утомительный, но имеет право на жизнь.
- Используйте службу блокировки, чтобы не выполнять одну и ту же работу дважды.
Определенно это хорошо.
Недостатки, с которыми вам придется столкнуться.
- MongoDB — довольно молодой продукт, и в нем есть ошибки (иногда ошибка сегментации, дамп ядра), появляются новые возможности и т. д. Я использую его в продакшене, но с осторожностью.
Однако несомненным плюсом является высокий темп разработки (проект пишется не только волонтерами, но и компанией штатных людей), поэтому вы можете рассчитывать на быстрое исправление ошибок, помощь в решении ваших проблем и реализация ваших идей (если, конечно, они хорошие).
Коммерческая поддержка также доступна.
- Накладные расходы на хранение имен свойств.
- По умолчанию максимальный размер объекта составляет 4 мегабайта.
- На 32-битных машинах максимальный размер одной базы данных составляет 2 гигабайта .
Финита ла комедия!
Страница проекта - МонгоБД .Найден эталон MongoDB против MySQL .
Эта статья рискует начать серию о MongoDB. В следующий раз я подробнее расскажу о шардинге, MapReduce и приведу живой пример.
Друзья, спасибо за внимание! Буду рад конструктивным комментариям.
Продолжение опубликовано: «MongoDB — готовим хороший кофе» .
Теги: #Web 2.0 #mongodb #базы данных #NoSQL
-
«Взломайте Нас, Чтобы Сделать Это Красиво»
19 Oct, 24 -
Архитектура 3Par Inserv
19 Oct, 24