Марш против RDBMS или проекты распределенных хранилищ (key-value stores)

    candybar2Вот вы часто создаете проекты? И, наверное, везде применяете базу данных, в частности, MySQL (а кто-то и PostgreSQL). Но вот что интересно, по опыту да и просто после чтения описания различных архитектур видно, что далеко не везде в проекте нужны ключевые особенности баз данных, во многих случаях базу используют просто как некоторое хранилище обычных данных. Например, в системах кеширования базы обычно не применяются, более того, кеширование как раз используют для того, чтобы избежать лишних запросов. А что используют для кеширования наиболее часто? Memcached. А что это такое? Это распределенная система хранения данных на основе хеш-таблицы. В общих чертах, это просто хранилище пар ключ-значение, над которыми можно производить только основные операции — запись, чтение, удаление и проверку на присутствие. Да-да, нет никаких фильтров, выборок, сортировки, самый максимум — система тегов для выборки одним запросом всех связанных записей. И во многих случаях такого функционала вполне достаточно.

    Я отнюдь не фанатик, и в реальных проектах лучшей будет комбинация из обычной, реляционной базы и специализированного хранилища данных. Более продвинутые системы, хранящие не просто пары ключ-значение, а и дополнительную мета-информацию об объекте, уже приближаются по возможностям к базам данных, их иногда называют документ-ориентированными базами (хранилищами), так как единицей информации, над которой происходит работа, является документ и ассоциированные с ними данные.

    Вторым критерием или особенностью является распределённость. Для СУБД это часто решается достаточно сложно или при помощи сторонних средств. Хранилища данных строятся на основе DHT (Distributed Hash Table) и изначально готовы к распределенной работе, обеспечивая масштабируемость и устойчивость к отказам отдельных узлов. В одних системах это решается за счет среды (например, если хранилище работает поверх Erlang VM), вторые используют встроенные средства распределенной работы (например, JGroups для систем на Java), либо собственные решения, как Memcached.

    Немаловажна и полная готовность таких систем для работы в Cloud-среде, не даром именно такое хранилище работает у Amazon (S3 и SimpleDB). Всем известный BigTable от Google также, по большей части, как раз система хранения и обработки пар ключ/значение. Из-за простоты и даже тривиальности API (но не всегда и внутреннего устройства, хотя оно и проще чем у стандартных SQL DB) решения отлично масштабируются (как на чтение, так и на запись), в том числе и динамически, без перерыва в работе. Так что если у вас есть или будет кластер, присмотритесь к таким решениям. Но есть один момент, о котором стоит упомянуть — очень часто такие системы работают только с хранением данных в памяти, если же требуется постоянное хранение, используются бек-енд системы, в том числе и хранение в обычной реляционной базе данных, хотя это часто может налагать ограничения на данные и их параметры (а также замедляет работу).

    Для чего же можно такое применить? Да везде, где у вас есть потребность хранить большое (практически неограниченное) количество данных, которые могут быть разбиты на отдельные независимые блоки. Это могут быть отдельные статьи, фотографии, видео или другие большие бинарные объекты, записи в логе, профайлы пользователей, сессионные данные (кстати, мы раньше анонсировали свою экспериментальную открытую разработку, сессионный сервер на Java для распределенного хранения сессий РНР приложений, аналогичное решение есть в промышленном Zend Platform). В большинстве случаев все ограничивается либо набором бинарных данных, либо текстовой строкой с данными или кодом в сериализированном виде, поэтому данные можно как использовать дальше в программе обработки, либо сразу отдать клиенту — именно так делает плагин для Nginx, который смотрит в Memcached и, если там есть запрашиваемый контент, отдает напрямую, минуя вообще обращение к вашему скрипту. Сейчас я, к примеру, проектирую чат-сервер, там как раз в качестве основного хранилища данных будет использован распределенный кеш (Java-система, использующая кеш с репликацией через JGroups), который по сути такое же хранилище данных в виде ключ и значение.

    Ладно, хватит теории, посмотрим, какие существуют системы хранения на рынке (конечно, open source).
    • Project Voldemort — один из интереснейших проектов (планирую рассказать о нем как то подробнее). Написан на Java, реализован шардинг (partitioned) и репликация данных. Если требуется постоянное хранение, используется BerkleyDB или MySQL, можно и свое хранилище дописать, система хранения основана на плагинах, потому это достаточно просто. К сожалению, похоже, что есть только API для Java-приложений (либо использование Facebook Thrift протокола для других клиентов). Из данных можно хранить структурированные данные (массивы), blob (двоичные пакеты данных) и обычный текст. Определенные сложности есть при горячем масштабировании, добавление новых нод в кластер не самое простое действие.
    • Scalaris — транзакционная система хранения, основанная на Erlang, при этом работает только с данными в памяти, не используя постоянного хранения на диске. Для отказоустойчивости используют шардинг и репликацию, а также «non-blocking Paxos commit protocol» (надо будет подробнее изучить, что это такое). Сервер имеет API для Java, Erlang и встроенный JSON RPC для взаимодействия с другими клиентами. Может масштабироваться достаточно легко и в любое время (платформа Erlang-а прекрасно для этого приспособлена).
    • MemcacheDBмы уже писали ранее об этой системе, использует только репликацию и хранилище на диске с использованием BerkeleyDB. Наверное, простейший из всех проектов, как в установке так и в использовании, а если мы и так используете инфраструктуру на основе Memcached, то это система идеально в нее вписывается.
    • ThruDB — проект, основанный на Apache Thrift framework (открытом проекте развития протокола Thrift, разработанного Facebook). На самом деле это даже не один проект, а целое семейство сервисов для построения инфраструктуры (которые, в свою очередь, базируются на других открытых разработках) — собственно, сам сервис хранения данных с бекендами на MySQL, Amazon S3, BerkeleyDB, а также сервис очередей сообщений, сервис масштабирования, система хранения документов и даже сервис индексирования и поиска данных (использует CLucene, порт Java Lucene на С). Клиентские библиотеки есть для разных языков, в принципе, достаточно порта протокола Thrift. Очень интересное решение, если вам необходимы многие из перечисленных функций сразу.
    • Apache CouchDB — документо-ориентированная система хранения данных на базе Erlang, использующая RESTful HTTP/JSON API для взаимодействия с клиентами. Для распределённости используется инкрементная двухсторонняя репликация и автоматическое разрешение конфликтов. Кстати, может использовать JavaScript в качестве языка запросов документов. Для устойчивости используется хранение данных на диске (собственный формат) и репликации на других нодах. Исходя из сетевой природы протокола, база может работать с любым клиентом и платформой, которая может сформировать JSON HTTP запрос, включая напрямую запросы от веб-страницы (JS).

    В список не вошли ещё несколько систем — например, Hadoop HBase, Cassandra, Hypertable, Dynomite, Kai, Ringo.

    Интересно заметить, что в основном для такого рода систем используют или специализированные языки и платформы (Erlang здесь почти вне конкуренции) или уже ставшие классикой и мейнстримом серьезные системы вроде Java, и лишь в редких случаях базируется на собственных разработках на С/С++.

    Разрабатываете высокопроизводительную систему, не обязательно веб? Нуждаетесь в специфическом хранении данных, при этом хотите получать их самым простым способом, масштабировать «в шырь и ввысь», даже не останавливая ни на секунду работы? При этом данных может быть много, но все они простые и сводятся к строкам или сериализированным структурам и двоичным блокам? Надо надежное хранение данных, распределённое и устойчивое к сбоям? Если хоть на один из этих вопросов ответ «да», вам стоит посмотреть хоть пару проектов из списка, возможно именно они позволят вашему проекту выдержать нагрузки и уверенно развиваться.

    P.S. Оригинальная статья, которая подтолкнула меня на написание — там хорошая сравнительная таблица систем.
    Метки:
    Поделиться публикацией
    Похожие публикации
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 31
    • +5
      code.google.com/p/redis/
      Redis is a key-value database. It is similar to memcached but the dataset is not volatile, and values can be strings, exactly like in memcached, but also lists and sets with atomic operations to push/pop elements.

      Redis is pretty fast!, 110000 SETs/second, 81000 GETs/second in an entry level Linux box.

      для php есть готовый класс code.google.com/p/redis/source/browse/trunk/client-libraries/php/redis.php

      зы пока присматриваюсь к проекту
      • +1
        интересно очень, спасибо, посмотрим
        • 0
          интересно — почему SET (запись) настолько больше производительность, чем GET. Собрал вот на хостинге у себя, вроде работает, без проблем. Попробую написать чат на этом, может не придется Java поднимать (хотя там больше фишек конечно). Скоро напишу тогда отдельный пост
        • +2
          по НЕреляционные базы уже наслышаны, а вот привести пример применения в проекте, только не гипотетический, а реального применения
          • +1
            В J2ME MIDP есть хранилище Record Management System (RMS). Вот это и есть реальное применение.
            • +5
              Мы используем CouchDB для хранения регистрационных данных пользователей. Это как бы портал с централизованной регистрацией, и всем сайтам которые являются частью портала мы раздаем эту информацию о пользователях элементарно делая http запросы к серверу CouchDB. С помощью функций Map мы получаем пользователей по тем или иным критериям (аналог sql WHERE conditions), а задав функцию Reduce мы что-то вычисляем, например число мальчиков или девочек :)
              • +2
                спасибо за прекрасный реальный пример! может напишете как то статью об этом?
                • 0
                  Для аналогичных целей мы используем MemcacheDB.
                  Первоначально для всего использовался связка mysql+memcache, естественно активно применяли шардинг, но когда число пользователей перешло за полтора миллиона, поняли что систему авторизации надо перевести на что-то простое и быстрое.
                  Главная проблема с которой стокнулись — ошибка connection timed out при росте MemcacheDB базы данных на модуле pecl-memcache на PHP.
                  Пытались достигнуть стабильности несколько дней, менятяя таймауты, версии MemcacheDB, собирая отдельные компоненты из разных версий.
                  В итоге, отчаяшись написали письмо Steve Chu, автору MCDB — и, о чудо, через день пришел ответ с рекоммендацией использовать модуль pecl-memcached (http://pecl.php.net/package-info.php?package=memcached) от небезызвестного Andrei Zmievski, использующий libmemcached в качестве средства соединения с memcache.
                  В итоге авторизация уже два месяца стабильно работает на memcachedb показывая значительно лучшие результаты по сравнению с mysql+memcache
                  • 0
                    У меня назрел вопрос, что будет с вашей базой MemcacheDB если случайно пропадет питание? Какойто бекенд существует для персистентного хранения данных?
                    • 0
                      MemcacheDB is a distributed key-value storage system designed for persistent. It is NOT a cache solution, but a persistent storage engine for fast and reliable key-value based object storage and retrieval. It conforms to memcache protocol(not completed, see below), so any memcached client can have connectivity with it. MemcacheDB uses Berkeley DB as a storing backend, so lots of features including transaction and replication are supported.

                      что будет с обычной базой? аналогично.
                      • 0
                        Так это по сути тоже самое что использовать BDB4 напрямую, там ведь совсем тупое хранилище, никаких стуркут, только ключ-значение. Теоретически, если бы вы использовали Berkeley DB напрямую из PHP, то работало бы все быстрее, но, так как мир не идеален, пришлось бы столкнуться с проблемами блокировки файловой системы при паралельных запросах. MemcacheDB по сути ничего общего, кроме протокола обмена, с настоящей Memcached не имеет :)
                      • 0
                        Вообще тут две вещи.
                        1. Делать репликацию на еще один мцдб для быстрого восстановления.
                        2. Дублировать все в бэкэнд в виде мускуля и по крону раз в день проверять целостность например.
                        Вообще я тут статейку накатал как мы делали, сейчас в течении получаса в блог засуну свой :)
                  • +4
                    Согласен с вами, но мне бы вот хотелось бы узнать, как например хранить данные скажем чата двух юзеров. Как потом выбрать эти записи? Или скажем есть список статей. А как выбрать все статьи постранично? В итоге нужно где-то хранить набор ключей всех статей.
                    Автор! Пример, причём реальный, в студию! Я вот не понимаю как можно тот же memcachedb использовать без таблицы-связки в MySQL между к примеру юзером и контентом.
                    • +1
                      Чёрт, коммент глупый вышел. Вопросы все адресованы автору.
                      • +2
                        примеров принципиально не будет — в сети валом описаний кто где и как использует. Для реальных разработчиков это видно, где и как использовать, остальным без надобности.

                        В чем проблема чата двух юзеров? Если есть теги — помечаем ими записи, если есть функция в хранилище — выборки по диапазону ключей — еще легче (а это есть, например, в EHcache). Мемкешем также все пользуются и отлично работает.

                        Вопрос в том, что систему изначально надо проектировать на использование не реляционной структуры, тогда и будут совсем другие подходы к решению вопросов, а некоторый вопросов просто не будет.
                      • +2
                        это не НЕреляционные БД. это другое.
                        Вы видимо никак не разработчик веб-систем, иначе не было бы таких вопросов.
                        Любой кеш (система кеширования) использует такое, мемкешед, ehcache и прочие. многие поисковые системы использую как хранилище данных такое (Nutch). Google использует.
                      • +2
                        Допустим у меня список именно таких ключ/поле записей. Они записывались в архаичном порядке.
                        Нужно получить десятую страницу по двадцать записей в каждой, отсортированных по полю.

                        Придётся ли получать все записи, сортировать, а потоп отсчитывать с 200ой по 220ую?
                        • +3
                          вы берете абстрактную задачу, описанную в терминах реляционной структуры и пытаетесь ее переложить напрямую на совсем другую структуру.

                          мап/редуце вам в помощь, выше писали про CouchDB к примеру, решается. В чем проблема сразу хранить блоками по 10 — 20 — 50 записей, и выбирать их вместе.
                          • 0
                            одна запись изменилась == переписать все 20?
                            • 0
                              а если записи не могут изменятся? Это лог или что-то еще?
                              Храните связанные списки — ключ (хеш временного интервала) => список ключей (ключ => хеш статьи) и потом выборка связанных. Задачу сразу нужно проектировать под реализацию
                        • 0
                          Можно так же добавить Mnesia — распределенная БД на Эрланге. Что интересно для нее есть плагин реализующий помимо стандартного API доступ с помощью SQL.
                          • 0
                            ayende.com Oren Eini пишет сейчас как раз такую штуку на .Net причем в данный момент идет планирование и он описывает в постах все архитектурные решения
                            • 0
                              MongoDB:

                              mongodb.org/ — оф. сайт
                              github.com/mongodb — код (текущая версия — 0.8)

                              Есть обвязки для Java, Python, Ruby, C++, PHP, Erlang, Factor и др.
                              Обвязку для Python я недавно тестировал в домашних условиях; очень простой, гибкий, удобный API.

                              Сравнивать с CouchDB довольно сложно. Пока не берусь это делать.

                              Вот что они сами о себе пишут:

                              MongoDB is a high-performance, open source, schema-free document-oriented data store that's easy to deploy, manage and use. It's network accessible, written in C++ and offers the following features:

                              * Collection oriented storage — easy storage of object-style data
                              * Full index support, including on inner objects
                              * Query profiling
                              * Replication and fail-over support
                              * Efficient storage of binary data including large objects (e.g. videos)
                              * Auto-sharding for cloud-level scalability (Q209)
                              • 0
                                ага, интересная система, я о ней писал — разработчики — это стартап создавший свою платформу CloudComputing — abrdev.com/?p=409 (10gen платформа)
                                • 0
                                  хотя странно, раньше была вся платформа, теперь переключились только на базу что ли
                                • 0
                                  Это по сути объекто-ориентированная БД не key-value хранилище данных.
                                  Вот еще одна разработка объектно-ориентированного хранилища

                                  hivext.ru/index.php/Структуры
                                  и пример как создавать типы и объекты через консоль
                                  forum.hivext.ru/index.php?topic=6.msg9#new
                                • 0
                                  А как документировать такие структуры? В rdbms ER модель, а тут как?
                                  Я не из бюрократических соображений а про то, как один человек может написать о данных так, чтобы разработчик клиента понял, что ему надо открывать-сохранять.

                                  Bigtable (GFS, Google AppEngine), AmazonS3 — это из этой же оперы или не совсем?
                                  • 0
                                    а в чем проблема? ER модели надо как раз потому что структура в БД очень сложная часто, здесь все намного проще. В чем проблема вести нормальную документацию?

                                    Да, как раз из той.
                                    • 0
                                      Представьте себе, что таблица key-value store — это полностью нормализованная РСУБД «в пределе». ;)
                                      • 0
                                        Скорее полностью денормализованная. )
                                        • 0
                                          не надо терминами бросаться без головы… Что значит полсностью нормализованная? 5 ил 6 -ая нормальные формы… По контексту наверно полностью денормализованная. Но радости то от этого мало, ибо при денормализации страдает целостность данных.

                                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.