Пользователь
0,0
рейтинг
16 ноября 2009 в 11:48

Разработка → Riak — веб-ориентированная система хранения данных



Немного статей на хабре посвящены новому движению в IT индустрии — NoSQL. Я решил изменить это и написал статью-перевод-обзор об одном из докладов с конференции NoSQL прошедшей 5 октября в Нью-Йорке. В этой статье будет говорится о системе Riak, с которой мне довелось иметь счастье работать последнее время.

Что такое Riak? Многие модные слова популярные сейчас, можно отнести к Riak. Riak — это документно-ориентированная база данных. Riak — это децентрализованное key-value хранилище данных, с поддержкой стандартных операций — get, put и delete. Riak — это распределенное, масштабируемое, отказоустойчивое решение для хранения информации. А так же Riak — это система с открытым исходным кодом и поддержкой обращений с помощью HTTP, JSON и REST. Ну и конечно RIAK — это NoSQL.

Если копнуть глубже, можно увидеть, что на Riak оказало сильное влияние Amazon Dynamo, теорема CAP (Consistency, Availability and Partition Tolerance) Эрика Бревера (Eric Brewer), сама система Интернета в целом, а так же опыт команды разработки Basho в разработке сетевых сред. Мы начали разрабатывать Riak осенью 2007 года, для использования в двух приложениях для Basho, которые были запущенны на Riak и работали на нем большую часть времени.

Чтобы понять почему Riak настолько мощный, требуется рассказать немного теории. Вначале поговорим об Amazon Dynamo.В документе описывающем Amazon Dynamo есть три термина для описания поведения распределенной системы хранения данных: N, R и W. N — это количество реплик каждого значения в хранилище. R — количество данных реплик для выполнения операции чтения. W — количество реплик необходимых для выполнения операции записи. Цель Riak — перенести N, R, и W в логику приложения. Это позволяет Riak адаптироваться к требованиям отдельных приложений.



Riak использует разные значения N для каждого сегмента (bucket). Например все объекты в сегменте «artist» будут иметь одинаковое значение N, а объекты в сегменте «album» совсем другое. Система использует непротиворечивый алгоритм хеширования для выбора места сохранения N количества реплик ваших данных. Когда поступает запрос, Riak использует хеширование для преобразования текстового ключа в 160-битное число. Когда узел кластера добавляется в Riak, он получает части от 160-битного пространства ключей. Узел имеющий ближайшее значение хэша от ключа (160-битное число) и содержит в себе первую реплику. Остальные N реплик сохранены на узлах с другими N-1 частями 160-битного пространства ключей.Непротиворечивый алгоритм кэширования очень важен — он позволяет каждому узлу Riak выполнить любой запрос. Поскольку любой узел может вычислить, с какими именно другими узлами необходимо связаться, чтобы выполнить запрос, любой узел может выступать в качестве организатора для любого клиента. Тут нет управляющего сервера, нет единой точки для сбоя в системе.



Riak использует разные значения R для каждого запроса. Каждый раз когда вы делаете запрос на получение данных, вы можете использовать разное значение R. Значение R определяет количество узлов, которым необходимо вернуть успешный ответ, перед тем как Riak вернет запрашивающему клиенту ответ. Riak пытается прочитать все возможные реплики (N), но когда будет достигнуто значение R, данные будут отправлены обратно клиенту.



Riak использует разные значения W для каждого запроса. Значение W определяет количество узлов, которым необходимо вернуть успешный ответ, перед тем как Riak вернет запрашивающему клиенту ответ. Riak пытается записать все возможные реплики (N) данных, но когда будет достигнуто значение W, результат будет отправлен обратно клиенту.

Предоставление клиенту возможности для указания значений R и W во время запроса, означает, что во время запроса приложение может указать точно, сколько узлов могут выйти из строя. Это очень просто: для каждого запроса, N-R (для чтения) или N-W (для записи) узлов может быть недоступно, однако кластер и данные будут по-прежнему вполне доступны.



Итак, в примере который мы использовали с N=3 и R=W=2, мы можем иметь 3–2=1 узел недоступным в кластере, но кластер по прежнему будет предоставлять данные. Для особо важных данных, мы можем увеличить значение N до 10, и если мы все ещё будем использовать значение R или W равное 2, мы можем иметь 8 недоступных узлов в кластере, но запросы на чтение и запись будут проходить успешно. Riak дает возможность изменять значения N/R/W так как это хороший способ улучшить поведение приложения при использовании теоремы CAP.

Если вы знакомы с теоремой CAP Эрика Бревера, вы знаете, что есть три аспекта, которые необходимо учитывать при рассуждениях о хранении данных: целостность данных, доступность данных в хранилище, и устойчивость к разделению. Если вы знакомы с исследованием, вы также знаете, что невозможно реализовать систему отвечающую всем трем условиям.

Поскольку вы не можете реализовать все три условия, большинство систем хранения данных используют два. Riak позволяет, не только выбрать любые из них, но и разные приложения могут выбрать различные объемы каждого. Вероятнее всего вы выберите доступность и устойчивость к разделению. Однако вы разрабатываете аппликации которые работают на реальных машинах и вы хотите чтобы они были доступны в любое время для пользователей. Структура Riak реализована для поддержки этой возможности (мы хотим чтобы наши приложения работали все время). Это означает, что вы готовы пожертвовать целостностью данных. Есть много советов как выв можете гарантировать целостность данных (например read-your-writes) в документе описывающем Amazon Dynamo и я советую вам перечитать этот документ.

Вот простой пример как может быть решен вопрос с целостностью данных. Давайте посмотрим на кластер который уже работает и имеет документ с версией 0.



Вдруг в сети происходит сбой. Узлы 0 и 2 находятся в Нью-Йорке, узлы 1 и 3 в Лос-Анджелесе и трансконтинентальная связь рвется. Как поведет себя каждая часть кластера? Если вы установили значения N/R/W надлежащим образом, обе части кластера по сути будут предоставлять версию 0 документа, как и раньше. Клиенты не будут знать о сбое. Теперь предположим что клиент внес изменения в документ, хранящийся в половине кластера находящегося в Нью-Йорке (вы же указали N/R/W так, чтобы это было разрешено?). Этот клиент ввел некоторое несоответствие. Теперь клиенты присоединившиеся к части кластера находящегося в Нью-Йорке получат версию 1 документа, в то время как клиенты присоединившееся к части находящейся в Лос-Анджелесе получат версию 0 этого документа. Теперь предположим что трансконтинентальная связь восстанавливается и обе половины кластера работают вместе. Что должен сделать Riak с двумя разными версиями документа?

В этом случае Riak использует алгоритм вектора времени, для определения какая версия документа более корректная. Алгоритм вектора времени это специальная реализация алгоритма временных меток Лампорта (Lamport clocks / Lamport timestamps). В отличии от обычных временных меток, система временных меток Лампорта построена таким образом, что происхождение и преемственность, может быть определена путем простого сравнения. Каждый раз когда данные сохраняются в Riak, их вектор времени увеличивается, и когда кластер восстановиться Riak сможет определить какие данные сохранить. В нашем случае Riak определит что версия 1 является приемником версии 0, и версия 0 будет заменена версией 1, и данные снова будут целостны.



Все становится немного более интересно, если в то время как части не связанны, клиенты внесут изменения в обоих частях кластера. Теперь когда кластер восстановится, вектор времени покажет, что ни одна из версий является преемницей другой версии. Riak не может определить какая из версий должна быть выбрана, поэтому в этом случае как и с возможностью изменить значения N/R/W, Riak переносит возможность урегулирования конфликта в приложение. Вместо реализации произвольного правила выбора версии как это сделано в других системах, Riak возвращает оба значения приложению предоставляя возможность выбора более верного варианта. Конечно если вы хотите использовать просто правило — данные пришедшие последними и используются, в Riak есть простой флаг для включения такого поведения (allow_mult свойство сегмента)



После всей этой теории как насчет нескольких примеров кода для демонстрации как легко работать с Riak?

Так как Riak написан на Erlang, давайте начнем с Erlang.



Первая строка кода описывает присоединение нашего клиента к кластеру Riak. Вторая строка создает новый объект (документ, пара ключ/значение). Третья строка сохраняет объект в Riak. Четвертая возвращает объект обратно из Riak. последние две строки изменяют значение нашего объекта и сохраняют его снова в кластер Riak.

Если вы не хотите использовать Erlang, Riak так же поставляется с библиотеками для Python…


…Riak так же имеет библиотеки для Ruby…

… Java…


… PHP…

… JavaScript…

…но на самом деле все эти библиотеки работают с Riak с помощью стандартного RESTful HTTP, и это позволяет использовать Riak на любой системе поддерживающей HTTP — например используя инструменты командной строки такие как curl или wget.


Это хорошо когда вам нужно отправить или получить данные из Riak, но что делать когда вы хотите сделать запрос по нескольким объектам одновременно? Это же NoSQL, ведь так? Как насчет небольшого Map/Reduce?


Система Map/Reduce Riak имеет много общего с другими системами Map/Reduce. Функция Map происходит на узле где находятся данные, увеличивая локальность данных одновременно с распределением вычислений в кластере. Часть Map/Reduce Riak которая более всего отличается от других решений заметна в том, что Riak не запускает метод Map над всеми данными в сегменте (bucket). Вместо этого Riak дает возможность клиенту предоставить список ключей объектов на которых должен быть запущен метод Map. Методы Map могут предоставлять больше ключей для более поздних фаз выполнения методов Map, но список ключей для метода Map должен быть определен всегда. Конечно вы можете указать любое количество ключей которое вы хотите, например если вы хотите выполнить метод Map по всем значениям в сегменте, достаточно включить их все в запрос Map/Reduce (функции list_keys или list_bucket могут быть полезны в таких случаях).

Различия в реализации Map/Reduce Riak при сравнении с другими системами обусловлены сильным желанием поддержки ссылок в Riak. Первый вопрос при переходе из мира RDBMS это — «Как я могу организовать связи между моими данными?» Было решено что лучший ответ на этот вопрос — ссылки.


Например если вы хотите организовать связи между записью исполнителя и несколькими записями альбомов, вы хотите создавать ссылки к альбомам в записи исполнителя. Аналогично вы можете создать ссылки в записи альбома к записям композиций входящим в этот альбом. Как только вы добавите ссылки и определите как Riak может получить эти ссылки из ваших объектов, вы получите доступ к новому синтаксису Map/Reduce. Например в данном примере вы можете видеть простой синтаксис позволяющий нам сказать — «Начни с исполнителя REM, потом следуй ко всем альбомам с которым связан исполнитель, потом следуй ко всем композициям с которыми связан альбом, потом извлеки имена этих композиций." Результатом этого запроса будут имена всех композиций REM которые были когда-либо выпущены.

Разработчики решили что link-walking (переход по ссылкам) настолько полезный, что даже реализовали URL синтаксис для него. Вверху вы можете видеть ссылку похожую на URL, и выполнение GET запроса по этому URL вернет вам список всех объектов композиций, который ранее мы получили в примере с Map/Reduce.

Можно ещё много чего рассказать про Riak, включая как создавать подключаемые бэкэнды, как использовать систему событий, как отслеживать состояние кластеров Riak и как реализовать межкластерную репликацию. Но это подождет до другой презентации.

Если вы заинтересованы в получении дополнительной информации, вы можете посетить сайт http://riak.basho.com/ где вы можете изучить документацию и загрузить Riak для ваших экспериментов. Так же существует список рассылки riak-users@lists.basho.com. Ну и конечно вы можете посмотреть видео данного доклада.

***
Надеюсь вы почерпнули из данной статьи много интересной и полезной информации. В дальнейшем если данная тема найдет отклик на сайте, торжественно заявляю, что буду продолжать серию статей на тему NoSQL. Передаю респекты командам проектов Translated.by и Типограф, благодаря им создание данной статьи было приятным времяпрепровождением.
Andy One @SilenceAndy
карма
197,5
рейтинг 0,0
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (32)

  • 0
    С виду вроде штука вроде интересная, надо будет поиграться на досуге.
  • –9
    Напоминает обычный memcache, со своей либой для выбора сервера данных, или еще лучше — memcacheq или memcachedb.
    • +6
      Отличий о memcache очень много, начиная от того, что Riak хранит данные не в памяти а на жестких дисках, и заканчивая упором на fault tolerance (отказоустойчивость). Они схожи в одном — оба NoSQL продукты.
      • –8
        memcacheq тоже складывает всё на диск в berkleydb, и при ребуте восстанавливает «куда надо».

        Riak — это некий велосипед для тех, кто не может построить его из уже существующих решений.
        • +5
          У обоих продуктов разные цели. Riak направлен на то чтобы дать возможность разработчикам сделать массивные продукты с максимальной отказоустойчивостью. memcacheq — это система очередей, а не хранения данных. Врятли с ее помощью мы сможем организовать систему которая сможет хранить несколько десятков терабайт данных, и предоставлять при этом Map/Reduce функциональность.

          Riak — это не велосипед, это скорее санки. Когда все изобретали велосипеды, ребята и basho (бывшие разработчики из Akamai) поставили себе сделать отказоустойчивую систему, исследовали возможности и уже готовые реализации, дабы не ходить по граблям. Я не говорю что система идеальна, но поверьте, она заслуживает внимания, если вы занимаетесь разработкой больших проектов.
          • –3
            Отказоустойчивость строится не только на программной среде. Достаточно одного гвоздя в винчестер, чтобы убить даже мастер-сервер. А гвоздями могут быть и питание по 1й категории, и резервные каналы и всё, что стоит до и после Riak.

            В статье идет упор, что это отказоустойчивое решение, а не приложение. Получается, они установкой одной софтины гарантируют отказоусточивость всех компонентов, даже рубильника в серверной — что если его дёрнуть, аплинки не выключатся и все ноды будут отвечать на запросы…
            • +1
              Отказоустойчивость строится не только на программной среде.

              Отказоустойчивость строится не только на программной среде. Достаточно одного гвоздя в винчестер, чтобы убить даже мастер-сервер. А гвоздями могут быть и питание по 1й категории, и резервные каналы и всё, что стоит до и после Riak.
              1. Мастре сервера в системе нет. Это p2p.
              2. Мы говорим об организации отказоустойчивости с помощью архитектуры проекта, конечно если на датацентр упадет метеорит, это вас не спасет.

              Получается, они установкой одной софтины гарантируют отказоусточивость всех компонентов, даже рубильника в серверной — что если его дёрнуть, аплинки не выключатся и все ноды будут отвечать на запросы…

              Вы думаете сейчас на уровне системы с 10-20 серверами. Это решение для больших систем, прям БОЛЬШИХ. >100 серверов. Когда сервера стоят в разных датацентрах в разных странах. На меньших объемах это решение в общем не нужно. Можно использовать MySQL с репликацией и MySQL Proxy.

              Ну если уж вы мне не верите, посмотрите на Cassandra, эта аналогичная система используемая в Facebook. Вот ресурсы которые она использует:
              The system currently stores TB’s of indexes across a cluster of 600+ cores and 120+ TB of disk space.

              • –3
                Для разнесенных серверов по странам встает вопрос об актуальности данных на всех серверах. Даже Mysql-репликация может лагать — оптимально 1-2 секунды на тяжелые запросы, но ведь каналы могут падать и актуальность таких данных под вопросом.

                Riak не панацея от всех проблем, связанных с доступностью и актуальностью данных.
                • +2
                  Riak не панацея от всех проблем, связанных с доступностью и актуальностью данных.

                  Точно. В статье об этом написано.
            • +2
              Что-то вас понесло уже совсем в другую сторону.
  • +1
    Было бы здорово увидеть пару рабочих примеров. Не тестовых, а которые используются непосредственно в работе.
    Ну и производительность, конечно.
    • 0
      Тут наверно нужно понять что в данном подходе главное масштабируемость и отказоустойчивость.
    • 0
      К сожалению их не так много. В основном из общения с разработчиками в списке рассылки я понял, что на данный момент есть только один большой кластер Riak — у самих разработчиков. Тесты и свои впечатления от работы с системой, я постараюсь выложить в следующих статьях. Кстати я забыл упоминуть в статье о том, что система рассчитана на рынок Enterprise платформ.
      • +1
        Звучит заманчиво.
        Попробую накопать дополнительную информацию по данному вопросу.
        Ну и, конечно, ждём продолжения :)
  • +1
    Статья познавательная. Спасибо.
    Но я поражаюсь, как легко многие жертвуют целостностью.
    Отказ от целостности — это битые данные, глюки и жалобы пользователей.
    ИМХО на нетранзакционные хранилища можно переходить, только имея за плечами опыт работы с ACID-транзакционными базами данных, зная что значит каждая буковка в слове ACID и что она дает.
    • +1
      Всегда пожалуйста :)

      Но я поражаюсь, как легко многие жертвуют целостностью.

      Могу сказать почему. Реализация контроля целостности, более легкая задача. Для отказоустойчивости в большинстве случаев нужна продуманная и серьезная архитектура. Контроль целостности реализовать проще. Для контроля целостности можно использовать избыточность данных и хэши сообщений (проверка хэша сообщение и в случае повреждения либо повторный запрос либо получение с другого сервера). Но как сказано в статье можно выбрать всего 2 пункта из трех.
      на нетранзакционные хранилища можно переходить, только имея за плечами опыт работы с ACID-транзакционными базами данных

      Абсолютно согласен. Я бы еще посоветовал при использовании той или иной технологии, обдумывать какие фичи из нее вам нужны и расставить им приоритеты.
  • –1
    блин, сколько можно, не «вэб», а «веб».
    • 0
      Лучше уж пусть будет web
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Нет, в начале есть фраза: «Riak — это документно-ориентированная база данных.» Суть в том, что вы можете сами выбирать как использовать систему. Можно как key-value хранилище, а можете как документно-ориентированную базу данных (основных баз такого типа на данный момент 3 — Riak, CouchDB и MongoDB).
      • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Нет, я именно имею ввиду документо-ориентированную базу данных.

    Тут я описал базовый функционал. На сайте разработчиков есть список всех фичерсов системы.

    Насчет сравнения, думаю написать в следующей статье перевод интересного сравнения всех NoSQL систем.
    • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Я что-то не до конца понял про репликацию. В списке фич есть такая строчка «Masterless multi-site replication» для Enterprise-версии. Разве репликация не предполагается самим принципом, который вы описали (N, R и W)? Или это что-то другое?

    И ещё: сколько стоит Enterprise-версия или хотя бы от чего зависит цена?
    • 0
      Разве репликация не предполагается самим принципом, который вы описали (N, R и W)?

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

      сколько стоит Enterprise-версия или хотя бы от чего зависит цена?

      Честно скажу, этого я не знаю.
  • +1
    В таком случае другой вопрос: схема обеспечения целостности данных, описанная в топике, подразумевала репликацию внутри кластера или платную межкластерную репликацию? Просто вы оперировали как раз географически удалёнными узлами.
    • 0
      В статье шла речь о целостности данных внутри кластера. Межкластерная репликация как пишут сам разработчики нужна в случае если вы хотите сделать несколько кластеров read-only (простейший пример CDN) или для бекапов.

      • 0
        Т.е. получается, что можно настроить кластер так?: разделяем узлы на две половинки, одну половинка находится в датацентре A, другая — в датацентре B, и говорим riak'у, что он должен сделать так, чтобы на обоих половинках были полные данные? Можно?

        Если можно, то тогда непонятно, зачем нужна межкластерная репликация, если ту же функциональность можно обеспечечить и средствами одного кластера и бесплатно (просто не писать в одну из половинок).
        • 0
          Конечно можно.

          Вот простейший пример когда это нужно: у вас есть 2 кластера — продакшен и деплоймент. В продакшене хранятся и накапливаются данные используемые для обработки (скажем сторонние клиенты предоставляют вам данные). При разработке вам нужны эти данные, для тестов или для проверки, но вы сами понимаете делать это с данными находящимися в продакшене вам никто не даст, и правильным решением тут выступает именно репликация продакшен кластера на деплоймент.
  • +1
    хорошая статья и правильный рекрутинг, так держать! ;)
    • 0
      Спасибо :)
  • 0
    > Однако вы разрабатываете аппликации

    Даже промпт перевел бы «приложения»

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