Содержание


Введение в Riak.

Часть 2. Интеграция Riak как мощного кэш-сервера для Web-приложений

Использование Riak в качестве кэш-сервера для уменьшения нагрузки на серверы приложений и баз данных

Comments

Серия контента:

Этот контент является частью # из серии # статей: Введение в Riak.

Следите за выходом новых статей этой серии.

Этот контент является частью серии:Введение в Riak.

Следите за выходом новых статей этой серии.

Характер доступа к некоторым типам данных делает их идеальным объектом для кэширования. Например, сайты интерактивных ставок имеют интересные характеристики нагрузки: ставки и наборы событий запрашиваются часто, но обновляются относительно редко.

В таких ситуациях для работы с большими нагрузками нужна хорошо масштабируемая система со следующими характеристиками:

  • Система выступает как надежная кэш-память для уменьшения нагрузки на серверы приложений и баз данных.
  • По кэшированным элементам можно выполнять поиск, так что их можно обновлять и аннулировать.
  • Решение легко интегрируется в существующий сайт.

Система Riak – это хороший выбор для такого решения.

Riak является не единственным кандидатом для реализации такого решения; существует много других кэш-решений. Одним из популярных решений является memcached; однако memcached, в отличие от Riak, не обеспечивает репликацию данных, а это значит, что в случае останова сервера, хранящего конкретный элемент, этот элемент становится недоступным. Redis, еще одно популярное хранилище пар ключ/значение, которое можно использовать в качестве кэш-памяти, поддерживает репликацию посредством конфигурации главный-подчиненный; Riak не имеет концепции главного (master) узла, что делает систему отказоустойчивой.

Интеграция в Web-сайт

Любое решение должно легко интегрироваться в существующий Web-сайт. Это очень важно, поскольку иногда перенести все существующие данные в Riak невозможно (или даже нежелательно). Как упоминалось ранее, некоторые типы данных идеально подходят для кэширования, в частности, данные хранилища ключ-значение с доступом по первичному ключу. Такой тип данных больше всего подходит для переноса в Riak.

Как говорилось в первой части (EN) данной серии статей, есть несколько библиотек на PHP, Ruby и Java™, которые предоставляют программный интерфейс, сильно упрощающий интеграцию с Riak. В данном примере я продемонстрирую использование PHP-библиотеки и покажу, как интегрировать Riak с существующим Web-сайтом.

На рисунке 1 показана конфигурация системы для данного примера. Я опустил некоторые детали, такие как распределение нагрузки, сетевой экран и т.д. В данном случае серверы сами по себе являются простыми интерфейсными системами с установленным на них стеком программ LAMP.

Предполагается, что Riak используется только изнутри (не доступна извне) и работает в дружественной среде, т.е. отсутствуют задачи, связанные с безопасностью, такие как аутентификация. Это не такое плохое предположение, как может показаться, поскольку Riak все равно не имеет какой-либо встроенной авторизации; на практике функции аутентификации и другие функции безопасности следует делегировать приложению.

Рисунок 1. Простая интеграция в Web-сайт
Рисунок 1. Простая интеграция в Web-сайт

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

На рисунке 2 приведен пример простой формы, которую администратор может использовать для создания страницы ввода ставок в системе. Создайте эту форму на HTML и реализуйте в ней запрос POST к PHP-сценарию, приведенному в листинге 1; в качестве отправной точки можно использовать аналогичную форму из исходного кода, сопровождающего данную статью. Поле key, заполненное в форме, будет использоваться в качестве ключа для сохранения объекта в области памяти.

Рисунок 2. Пример формы для создания ставки
Рисунок 2. Пример формы для создания ставки
Рисунок 2. Пример формы для создания ставки

В листинге 1 приведен пример PHP-кода, демонстрирующего использование библиотеки PHP-клиента для интеграции с Riak. Замените путь к библиотеке PHP-клиента, указанный в require_once, на ваш путь к каталогу установки библиотеки. В данном случае я поместил ее в тот же каталог, в котором находится PHP-сценарий. По умолчанию все клиентские библиотеки для доступа к Riak используют порт 8098.

Листинг 1. Пример PHP-кода для интеграции с Riak
<?php

require_once('./riak.php');

# Здесь можно реализовать проверку того, имеет ли текущий пользователь
# соответствующие полномочия. Делегирована в приложение.

$client = new RiakClient('192.168.1.1', 8098);
$bucket = $client->bucket('odds');

$bet = $bucket->newObject($_POST['key']);        
$data = array(
    'odds' => $_POST['odds'],
    'description' => $_POST['description']
);
$bet->setData($data);

# Сохранить объект в Riak
$bet->store();

echo "Thanks!";
?>

Сохраните код в PHP-файл (дайте ему любое имя) и загрузите его и форму где-нибудь на вашем Web-сайте (например, на http://www.yoursite.com/riak-test.php). Заполните пример формы и отправьте ее. Для проверки работоспособности формы попробуйте извлечь элемент непосредственно из Riak, используя введенный при создании элемента ключ (см. листинг 2).

Листинг 2. Извлечение элемента из Riak
$ curl -i http://localhost:8098/riak/odds/<key>
...
{ "odds":"", "description":"" }

В этом примере интеграции использовался PHP-клиент, но подход аналогичен и для других языков и прикладных сред (например, Java или Ruby on Rails).

Непосредственная обработка запросов

Для интеграции Riak в имеющийся Web-сайт помимо клиентских библиотек можно применять пользовательские запросы непосредственно из Riak, используя ее в качестве простого HTTP-механизма. Для демонстрации такой возможности я создам простое приложение, которое может запрашивать страницы напрямую из Riak.

Загрузите исходный код к данной статье. Убедитесь, что Riak запущена, и выполните сценарий load.sh. Этот сценарий скопирует все HTML- и JavaScript-файлы в сегмент под именем demo. В данном примере используется JavaScript-клиент.

Для просмотра демонстрации укажите в браузере URL-адрес http://localhost:8098/riak/demo/demo.html.

После ввода в форму значений для создания ставки и отправки формы JSON-объект сохраняется в Riak. Свойства объекта будут соответствовать полям формы. Вы будете направлены на страницу, отображающую значение только что созданного объекта.

В листинг 3 показан исходный код, создающий объект из введенных вами значений. Значения key, odds и description – это значения, введенные в форму.

Листинг 3. Пример использования клиентской JavaScript-библиотеки в Riak
client.bucket("odds", function(bucket) {
    var key = $('#key').val();
    bucket.get_or_new(key, function(status, object) {
        object.contentType = 'application/json';
        object.body = { 'odds': $('#odds').val(), 'description': $('#desc').val() };
        object.store(function(status, object, request) {
            if (status == 'ok') {
                window.location = "http://localhost:8098/riak/odds/"+key;
            } else {
            alert("Failed to create object.");
        }
        }); 
    });
});

Как говорилось ранее, предполагается, что Riak выполняется в надежной среде. В этом случае отсутствует проблема безопасности при добавлении страниц, сохраняющих (извлекающих) элементы в (из) Riak, однако не стоит использовать эту функциональность в Интернете, не имея какой-либо системы аутентификации.

Несмотря на простоту, этот пример дает представление о том, как Riak напрямую обрабатывает запросы страниц. Для извлечения необходимых данных можно было бы, например, включить хранящиеся в Riak данные непосредственно в существующие Web-страницы либо путем использования методики JSONP или CORS (cross-origin resource sharing – междоменное использование ресурсов), в которой из-за политики same domain (одинаковый домен) AJAX-запросы ограничены тем же сервером, на котором размещена страница, либо направляя запросы в Riak через прокси, т.е. через ваши серверы.

Использование Riak для кэширования

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

Одной из таких возможностей является его подключаемая серверная система хранения (storage back-end); она определяет, как хранятся данные. Есть несколько вариантов, но я не собираюсь рассматривать их все (ссылки на дополнительную информацию приведены в разделе Ресурсы). Системой хранения по умолчанию является Bitcask – Erlang-приложение, предоставляющее программный интерфейс для сохранения и извлечения данных, поддерживаемых хэш-таблицей, обеспечивающей быстрый доступ к ним; данные являются персистентными.

Возможно, для данной статьи больше подходит система Memory. Для хранения всех своих данных Memory использует таблицу в оперативной памяти (по сути, используются Erlang-таблицы ets) и, если разрешено, заставляет Riak вести себя как LRU-кэш с установленным временем истечения срока хранения. Преимуществом хранилища в оперативной памяти является его значительно более быстрая работа по сравнению с использованием данных, извлекаемых с диска. Если данные хранятся в памяти (не персистентны) и узел завершает работу, данные, хранящиеся на нем, теряются. Но поскольку мы используем Riak как кэш, это не проблема – приложение всегда сможет извлечь данные из базы данных, как это было бы при использовании Riak в качестве основного хранилища данных. Riak реплицирует данные на несколько узлов кластера, поэтому они все равно будут доступны.

Система Memory входит в комплект поставки Riak. Для использования Memory откройте файл app.config для каждого узла в кластере, найдите свойство storage_backend и измените его с riak_kv_bitcask_backend на riak_kv_memory_backend. Теперь добавьте в конец файла код, приведенный в листинге 4.

Листинг 4. Использование серверной системы Memory
{memory_backend, [
    {max_memory, 4096},	%% 4GB of memory
    {ttl, 86400}        %% Time in seconds
]}

Измените значения на подходящие для вашей конфигурации. Перезапустите узлы в кластере.

Существует возможность запустить в кластере Riak несколько систем хранения. Это полезно при использовании разных систем хранения для разных сегментов. Например, можно настроить сегмент (назовем его cache) на использование серверной системы Memory, а для остальных сегментов, которые должны сохранять данные, использовать, скажем, Bitcask.

Теперь, когда Riak настроена на работу в качестве кэша, нам необходим какой-то способ обращения к данным в кластере либо для обновления, либо, например, для проверки по какой-либо причине (до истечения срока их действия).

Что-то ищете?

Как вы уже видели, для извлечения хранящихся в Riak данных с использованием HTTP-интерфейса создается URL-адрес, состоящий из названия сегмента и ключа извлекаемого объекта, а затем выполняется запрос HTTP GET по этому URL. Это абсолютно правильно, если известен ключ! Но иногда нам либо не известен ключ объекта, который мы хотим извлечь, либо необходимо извлечь набор объектов, соответствующих определенному критерию. Следовательно, нам нужен метод поиска объектов, хранящихся в кластере.

Вы уже видели, как запрашивать данные путем выполнения задания Map/Reduce для документов, хранящихся в кластере. Время выполнения запроса будет в общем случае прямо пропорционально количеству документов в кластере; чем больше документов, тем дольше выполняется запрос этих документов. Это не проблема для запросов, нечувствительных ко времени. Под ними я подразумеваю запросы, на которые пользователь не ожидает получить немедленный ответ. Для задач поиска нереально каждый раз (динамически) просматривать все документы; получение результатов может продолжаться минуты или часы!

К счастью Riak уже имеет решение этой проблемы – Riak Search. Система Riak Search предоставляет функциональность, необходимую для поиска документов, хранящихся по всему кластеру. Тема поиска слишком обширна для подробного рассмотрения в данной статье, но общий принцип таков: документы морфологически размечаются (Riak Search использует стандартные анализаторы Lucene) и добавляются в инвертированный индекс. Затем к этому индексу выполняется запрос, основанный на поисковых терминах, введенных пользователем. Новые документы тоже индексируются и добавляются в индекс.

По умолчанию функциональность Riak Search отключена. Перед использованием ее необходимо включить. Для каждого узла в кластере откройте файл rel/riakN/etc/app.config, найдите свойство riak_search и установите его в значение true. Перезапустите узлы в кластере.

Riak позволяет указывать имя функции, выполняемой перед или после добавления документа в сегмент, путем использования перехватчиков pre- и post-commit. Например, перед добавлением в кластер документа можно проверить, содержит ли он необходимые поля. Документ для поиска должен быть проиндексирован. Для этого установите перехватчик pre-commit для сегмента, в котором хранятся документы. Выполните команду $ rel/riak/bin/search-cmd install <bucket name>.

Эта команда установит перехватчик pre-commit riak_search_kv_hook для сегмента. Теперь при добавлении в этот сегмент документ будет анализироваться и добавляться в индекс. Анализатором по умолчанию является анализатор пробелов (whitespace); он обрабатывает символы в маркеры на основе пробелов, которые затем индексирует. Существует несколько различных анализаторов, кроме того вы можете определить ваш собственный.

Во многих случаях Riak Search знает, как индексировать ваши данные. Например, если в сегмент добавляется JSON-объект, значение каждого свойства будет индексироваться и к нему можно будет обратиться по имени свойства в строке запроса. Пример поиска приведен в листинге 5. Для более сложных структур можно определить свою собственную схему, указывающую Riak Search, как индексировать данные.

Необходимо уметь обращаться к проиндексированным документам. Одним из способов является выполнение запроса из оболочки Erlang. Например, запрос, приведенный в листинге 5, ищет в сегменте odds все ставки на скачки; для этого выполняется запрос свойства описания сохраненного элемента.

Листинг 5. Поиск в сегменте odds ставок на скачки
$ rel/riak/bin/riak attach

search:search(<<"odds">>, <<"description:horse">>).

Кроме того, Riak Search предоставляет Solr-совместимый HTTP-интерфейс для поиска документов. Apache Solr – это популярный корпоративный поисковый сервер с REST-подобным программным интерфейсом. Совместимость интерфейса с Solr позволяет отключить Solr (если он используется) и использовать возможности Riak Search для выполнения операций поиска. Например, для поиска ставок на конкретное событие с использованием интерфейса Solr можно выполнить команду $ curl "http:localhost:8098/solr/odds/select?start=0&q=description:horse".

Настроив поиск, можно искать элементы в хранилище данных, не зная их первичного ключа.

Заключение

Способность Riak масштабировать и надежно реплицировать данные, а также другие возможности (например, поиск), делают эту систему идеальным выбором для реализации кэширования сайтов с большой нагрузкой. Она легко интегрируется в существующий сайт. Благодаря возможности непосредственно обрабатывать запросы Riak можно использовать для уменьшения нагрузки на серверы приложений и баз данных.


Ресурсы для скачивания


Похожие темы


Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Open source
ArticleID=837384
ArticleTitle=Введение в Riak.: Часть 2. Интеграция Riak как мощного кэш-сервера для Web-приложений
publish-date=09252012