PHP

индекс
206,80

Реализация noSQL на PHP

Скорость, друзья, — вот одно из важных составляющих вашего проекта. Пока ресурс посещает 10-100 пользователей в день, то все нормально — пользователь радуется и приглашает к вам своих друзей, друзья своих друзей и так далее. Нагрузка растет…

Человеку, который смотрит фотки, читает блоги, слушает музыку в интернете, не важно на каком языке написан ваш сайт, какая используется СУБД и используете ли вы кэширование. Ему важно, чтобы доступ к интересному контенту был максимально быстрый.

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

Рассмотрим связку PHP+MySQL+Memcached.

Чтобы показать пользователю статью с комментариями, нужно:
  1. Посмотреть есть ли статья (с комментариями) в кэше
  2. Если нет, то сделать «дорогой» JOIN текста + комментариев
  3. Положить все в кэш
  4. Отдать контент пользователю
Большой минус в этом алгоритме — это мускульный JOIN (или любой другой СУБД).
Современная концепция noSQL появилась, как ответ нормализованным структурам данных.

Рассмотрим связку PHP+Memcached в предыдущем примере:
  1. Посмотреть есть ли статья (с комментариями) в кэше
  2. Если нет, то положить ее в кэш
  3. Отдать контент пользователю
На один пункт стало «легче». Нет JOIN, но где брать данные? Хранить в файлах.

Появляется понятие «документ» (например: статья с комментариями). Чтобы конкретнее разобраться в noSQL технологии, захотелось как всегда «придумать велосипед».

Прототип JIM2

Требуются: Apache + mod_php + php_xcache

Указываем путь, где будут храниться файлы:
define('STORAGE_PATH', 'F:\\tmp\\jim2');

Пример использования:

запись
$collection = new Collection();

$vasya = array
(
 'name' => 'Vasya',
 'sex' => 'male'
);

$masha = array
(
 'name' => 'Masha',
 'sex' => 'female'
);

$jim = array
(
 'name' => 'Jim',
 'sex' => 'male',
 'type' => 'dog'
);

$collection->put($vasya);
$collection->put($masha);
$collection->put($jim);

$collection->createIndex( array ('name+sex', 'sex') );

чтение
$collection = new Collection();

$keys = xcache_get('./index/sex/male');

foreach ($keys as $key)
{
 print_r( $collection->get($key) );
}
Особенности:
  1. Документы хранятся в виде ключ/значение
  2. По свойствам документа можно строить индексы (создаются дополнительные ключи)
  3. У каждого документа есть поле _rev, указывающее на версию документа. Это позволит избежать коллизии при блокировке файла на запись, так как проверяются версии документов
  4. Также сама коллекция хранит версию. Сделано для того, чтобы можно было преверять актуальность кэшей, построенных на базе коллекции документов
Чего еще нет, но будет:
  1. Выборка коллекции с помощью API
  2. Pagination
  3. … любое ваше предложение
P.S. Скорость на чтение я не сравнивал, так как очевидно, что прямое обращение к кэшу будет работать всегда быстро. А вот скорость вставки (100 элементов) порадовала: связка MySQL+memcached отстала (0.5417142) от JIM2 (0.4791223)
–7
9 января 2010, 17:29
11

комментарии (37)

+7
SerGold #
Вы правда считаете, что это будет быстрее нормальной схемы работы СУБД?
НЛО прилетело и опубликовало эту надпись здесь
+1
regeda #
Я считаю, что отказываться от СУБД рано. Хотелось пойти в другую сторону и посмотреть на альтернативные решения, которые могут иметь место
НЛО прилетело и опубликовало эту надпись здесь
+2
regeda #
Я время не трачу. Мне это интересно.
0
Psih #
Правильно совмещать СУБД классическую (для хранения связей) и NoSQL базы для хранения объектов, реализация которых на SQL сильно добавляет нагрузки. Т.е. балансировать надо, тогда всё будет ОК.
0
SerGold #
Как бы не ругали (О)РСУБД, и не смотря на существующие альтернатив, например MongoDB, в реальности РСУБД еще долго будут править бал…
–1
regeda #
РСУБД — будет править миром. Но в мире сеть еще много непознанного…
+3
missTerr #
Чрезвычайно интересно и настолько же голословно без хотябы синтетических тестов.
+1
Psih #
Это легко и очень очевидно. У вас затык именно в списке статей, постраничном выводе и.т.д. Без этого ваша статья просто не имеет ценности. А ведь это те вещи, без которых любой сайт не построишь практически.
+1
kykapa4a #
Зачем отказываться от удобства базы данных? Перестраивайте кэш при внесении изменений в базу, тогда при выводе данных вы будете работать только с ним непосредсвенно. Пункт 2 в ваших схемах будет исключён.
+1
zizop #
А чем ваше решение отличается от использования для генерирования динамики PHP+Apache+Mysql, а для отдачи кэша любой key-value базы (в которой уже есть все нужные возможности, и работает она также шустро) например Redis? Может стоит посмотреть в эту сторону…
–1
regeda #
В моем решении нет SQL.
+3
zizop #
Ок, кажись понял, вы делаете аналог txtSQL.
+2
Fr3nzy #
А как быть с ограничением количества операций ввода/вывода в секунду?
0
Fr3nzy #
Все-таки, такие вещи нужно хранить в ОЗУ. Быстрее вы ничего не найдете. И иногда просто FLUSH'ить данные.
0
standov #
пока хватает одной машины
0
regeda #
Так в основном все в ОЗУ и хранится…
+3
standov #
что за паника с джойнами? если вы по религиозным причинам не приемлите их — юзайте 2 запроса, ваш тест повеселил, у меня есть вопросы для соискателей на вакансию php-developer, там есть вопрос «опишите достоинства/недостатки кеширования в разделяемой памяти, memcache и файлах». нельзя говорить о серьезном хайлоаде и о превосходстве xcache над memcache.
0
standov #
имеется в виду одновременно говорить
0
regeda #
В моем решении можно использовать любой cache backend
НЛО прилетело и опубликовало эту надпись здесь
+1
TheMengzor #
Синтетические тесты в студию :-)
0
aktuba #
Чтобы показать пользователю статью с комментариями, нужно:

1. Посмотреть есть ли статья (с комментариями) в кэше
2. Если нет, то сделать «дорогой» JOIN текста + комментариев
3. Положить все в кэш
4. Отдать контент пользователю

Большой минус в этом алгоритме — это мускульный JOIN (или любой другой СУБД).
Современная концепция noSQL появилась, как ответ нормализованным структурам данных.

Рассмотрим связку PHP+Memcached в предыдущем примере:

1. Посмотреть есть ли статья (с комментариями) в кэше
2. Если нет, то положить ее в кэш
3. Отдать контент пользователю

Правильнее:

Рассмотрим связку PHP+Memcached в предыдущем примере:

1. Посмотреть есть ли статья (с комментариями) в кэше
2. Если нет, то получить из файла
3. Положить все в кэш
4. Отдать контент пользователю

Сильно сомневаюсь, что будет быстрее, особенно на архитектурах, отличных от пост-комментарии. Добавьте оценки постов/комментариев и потестируйте…
0
regeda #
Несомненно на есть архитектуры (наример. бухгалтерия), где без СУБД не обойтись никак.

Уточнение по поводу алгоритма — правильное. Только, чтобы сделать JOIN, эти данные тоже нужно откуда-то взять…
0
aktuba #
>Несомненно на есть архитектуры (наример. бухгалтерия), где без СУБД не обойтись никак.

Вообще, СУБД — это система управления базой данных. То, что получается у вас — тоже СУБД, хоть и на другой основе.

>Только, чтобы сделать JOIN, эти данные тоже нужно откуда-то взять…

Верно. Разница только в том, что для этого, обычно, используются индексы, по которым легко найти нужные данные. И тут возникает вопрос: получится ли у вас сделать структуру практичнее и удобнее, чем в большинстве популярных СУБД? Время на поиск файла (в вашем случае) обычно больше, чем на чтение данных из одного файла (в случае использования индексного файла).
0
regeda #
Я имел в виду СУБД — как SQL СУБД.

Пока что мое решение — это лишь прототип. Поставить его наравне с уже изместными MySQL, PostgreSQL, Oracle и другими нельзя.

Файловые системы тоже бывают разные. А сами документы кэшируются и чтение идет уже из памяти.
+1
FTM #
Когда только начинал кодить для веба, делал примерно то же самое. Вот только с СУБД куда удобнее и безопаснее.
НЛО прилетело и опубликовало эту надпись здесь
+1
remal #
Что мешает использовать NoSQL базы вместо того, чтобы городить такое извращение?
0
regeda #
академический интерес к подобному роду извращений
–1
Chikey #
сказал А скажи Б
взялся за NoSQL для высоконагруженного проекта используй «не PHP»
0
prolis #
Вы, случаем, не родственник?
Разработал драйвер баз данных, что дальше???
0
regeda #
Постебаться я тоже умею, только ничего хорошего из этого не выйдет…
0
beylbom #
Такое впечатление, что люди от безделья подыхают. Лишь бы всё подряд везде закэшировать и непопсово похранить
0
Avstralis6 #
Все файловые операции медленные, читать из \ писать в пайп базы намного легче и быстрее для системы.
Для высоко нагруженных проектов этот вариант вообще не подходит, все будет висеть т.к. винт один, и читать с него в несколько потоков синхронно нельзя, рейд незначительно исправляет ситуацию. ( к тому-же винты убиваются почти мгновенно). Необходим промежуточный кэш ( тот же memcached ) который будет собирать данные и выгружать \ подгружать блоки, что уже немного опасно, есть вероятность потерять кусок данных, которые помещены в кэш, но блок еще не выгружен на диск. Подобный механизм уже реализован в любой уважаемой СУБД. Вообще СУБД стараются помещать как можно больше данных в память ( индексы, таблицы, кеш результатов выборки) чтобы уменьшить нагрузку на диски, т.к. они являются узким местом в работе сервера. Тут вариант обратный :D

если join`ы не позволяет религия, местом хранения блоков лучше выбрать СУБД, а не файловую систему.

Изменение структуры хранения данных может помочь вообще отказаться от join в запросах.

«P.S. Скорость на чтение я не сравнивал, так как очевидно, что прямое обращение к кэшу будет работать всегда быстро. А вот скорость вставки (100 элементов) порадовала: связка MySQL+memcached отстала (0.5417142) от JIM2 (0.4791223)»

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

0
eugyn #
>А вот скорость вставки (100 элементов) порадовала: связка MySQL+memcached отстала (0.5417142) от JIM2 (0.4791223)

Когда по сети ложить/доставать в/из кэша будете, тогда и порадуетесь.

А так, рано радуетесь
:-)

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