Что такое CouchDB
Прочитал на Хабре про успехи npm и решил написать пост. npm – это пакетный менеджер и публичный репозиторий для node.js, и успехи реально очень впечатляющие.
Фишка в том, что этот репозиторий – база CouchDB. Не “веб-сервер плюс БД”, а именно просто БД. Кластер там, с обвесами – но основные функции выполняет CouchDB, вот на её мету прямой выход. И именно CouchDB там используется неспроста.
Доступность
CouchDB имеет сразу после установки уникальный набор фич, связанных с доступностью. По-отдельности они в других БД есть, а вот разом – нет.
По-хорошему, CouchDB сразу после установки становится веб-сервисом. Доступ к БД – только через http(s)-запросы, через REST-интерфейс, то-есть веб-сервер уже встроен в БД. Веб-приложение админки тоже встроено в БД, аж в двух версиях.
Система контроля доступа – простая, но совершенно железобетонная – тоже встроена в БД, как и механика авторизации.
БД умеет синхронизироваться в непрерывном режиме с другими экземплярами через http(s), в тч в режиме “мастер-мастер”. Протокол репликации хорошо документирован и основан на согласовании деревьев ревизий.
Последняя фича, например, значит, что можно иметь полную локальную “живую” копию npm. Можно даже в браузере, без установки CouchDB.
Хранение и запись
Сама по себе, как БД, CouchDB представляет из себя хранилище JSON-документов, но тут тоже есть целый ряд уникальных фич.
Операция записи/обновления – просто POST запрос, например, аяксом. Запись неблокирующая, это называется MVCC, и тут он честный, а не как в табличных БД.
У каждого дока есть ревизия, которая состоит из номера версии и случайного значения (типа 15-12efdab). При каждой записи в док версия инкрементится, а значение меняется. Записать в док можно только отправив значение предыдущей ревизии, причём если сохранённая ревизия не равна отправляемой, запись отменяется.
Запись идёт в режиме “append only”, ничего не пишется поверх. Это значит, что база помнит все ревизии документов до тех пор пока не будет выполнена операция очистки/оптимизации. Также это значит, что база выжимает из SSD-дисков всё, на что они способны – и при этом их бережёт.
И самое главное – к JSON-документам возможны файловые аттачи, примерно как к емэйлам. То-есть это не просто блобы, это блобы с именем и mime-типом.
Выборка по ключу
Нет ничего проще – GET-запрос типа domain/dbname/doc_id – например https://ermouth.couchappy.com/cwmanual/cw-Demo-Controls-4vx1 – сразу отдаст JSON-документ.
В этом документе есть приаттаченный файл – картинка. Она тоже доступна по прямой ссылке https://ermouth.couchappy.com/cwmanual/cw-Demo-Controls-4vx1/turing.jpg. Вот она, отображается прямо из CouchDB.
Выборка запросами
Любая выборка запросом из CouchDB – это выполнение map/reduce и выдача запрошенного диапазона ключей.
Именованные пары map/reduce функций, к которым выполняются запросы, хранятся в самой БД в специальных документах. Документ выглядит примерно так ermouth.couchappy.com/cloudwall/_design/cloudwall. Видно, что функция – javascript.
Запрос к этой map/reduce паре (в которой reduce, правда, нет) выглядит примерно так:
ermouth.couchappy.com/cloudwall/_design/cloudwall/_view/info?startkey="cw"&endkey="cwz"
На выходе – краткая информация о документах в базе, подготовленная map-функцией. В диапазоне ключей cw…cwz.
Важнейшее отличие CouchDB от других БД – результаты вычислений map/reduce кэшируются и повторно map-функции не вычисляются, если документ не обновился.
То-есть map/reduce не требует фуллскана каждый раз, как, например, это происходит в Mongo. Фактически map-функции используются для построения индексов.
Валидация записи и частичное обновление
POST-запросы на запись могут проверяться в БД функциями-валидаторами. Они тоже js и тоже хранятся прямо в БД как специальные документы. Например, вот эта функция не даст писать в БД, если вы не авторизованы:
Примерно такие же хранимые функции могут применяться для частичного обвновления документов.
Ну то-есть например надо обновить в документе только таймстамп. Чтоб не гонять весь док по сети, можно вызвать на сервере сохранённую функцию, которая это сделает “не отходя от кассы”.
Применимость CouchDB
Везде, где reads>>writes и структура хранимых данных – более-менее сложная. Также в силу специфики http и сериализации как читать, так и писать лучше сразу помногу.
Табличка вот по кейсам, 0 – совсем не подходит, 5 – лучше не придумаешь.
Версионированные хранилища доков | 5 |
Распределённые синхронизированные хранилища | 4 |
Хранилища частично нормализованных связанных данных | 1-4 |
Полностью нормализованные данные | 0 |
Быстрые логи | 2 |
Медленные логи / Агрегаторы логов для анализа | 5 |
Вообще большие наборы данных для анализа | 5 |
Необходимость транзакционной целостности | 0 |
Сложные повторяющиеся “фигурные” выборки | 4 |
Выборки сабсетов узлов документов (частей документов) | 5 |
Подключенные клиенты хотят уведомлений, что база обновилась | 4 |
Хранение файлов (типизированных блобов) | 4 |
SSD диски как хранилище | 5+++ |
Синхронизация / репликация по каналам с потерями и обрывами | 5+++ |
CouchDB вместо сервера приложений
В типичных задачах малого/среднего бизнеса бизнес-логика в общем довольно проста и не требует атомарности транзакций. По-хорошему такая целостность вообще очень редко когда нужна и недостижима для распределённых систем в общем случае, но это тема отдельного поста.
Так вот, жизнь показала, что в подавляющем большинстве случаев сервер приложений рядом с CouchDB не нужен вообще – хранимые функции прекрасно со всем справляются. То-есть получается связка из веб-приложения в браузере и БД на сервере, и между ними ничего, кроме сети и https-запросов.
Такая архитектура проста и надёжна, как железный лом – если в ней что-то и ломается (что почти невероятно), то мгновенно понятно что.
Единственное, что приходится делать вне CouchDB – это ограничивать доступ на чтение. Система доступов в самой CouchDB такая, что дать права на чтение пользователю можно только к целому бакету, но не к отдельным документам.
----
В общем, всем ребятам, кто в вебе или около, очень советую как минимум покрутить-попробовать. Тем более анонимные эксперты вот говорят, что эта технология – один из трендов 2015.
Есчо, на Винде тоже прекрасно работает.
no subject
1. Compact выполняется на лету (с потерей производительности, но не с полной остановкой) и может делаться автоматически по самым разным критериям. Всё это делается средствами CouchDB. Это абсолютно тривиальная операция.
2. Нет там таблиц. И репликация не предназначена для организации кластера, для этого есть другие инструменты.
3. См п.2
4. Нет, не обязательно требует. Сбои были, чтений всего файла не было ни разу.
Про последнее... Ну, я не буду прямо пальцем показывать, где оно у нас мягко говоря не минимальное, просто скажу – сбавьте апломб, вам не идёт.
no subject
1. Да, конечно, средствами CouchDB, я хотел немного другое сказать, про сам механизм:
http://docs.couchdb.org/en/1.6.1/maintenance/compaction.html
> During compaction of the target CouchDB creates new file with the .compact extension and transfers only actual data into. Because of this, CouchDB checks first for the available disk space - it should be twice greater than the compacted file’s data.
When all actual data is successfully transferred to the compacted file CouchDB replaces the target with the compacted file.
То есть минусы такие: затраты на компактификацию пропорциональны объему всех данных, а не только устаревших. Соответственно можно представить себе ситуацию когда не очень большой поток writes на очень большую базу приведет к тому, что компактификация не будет успевать отрабатывать.
Понятно, что можно много случаев придумать, когда это приемлимо. Я просто говорю, что это один из основных векторов критики CouchDB, думаю полезно его упомянуть, для целостности картины.
2. Хм, окей, а для чего предназначена? И что за инструменты?
4. Да, не требует, там append only + перезаписываемый заголовок с вершиной B-дерева в начале файла. Я скорее всего спутал с чем-то, возможно, с более ранней версией.
Забыл еще спросить про вот это:
> Запись идёт в режиме “append only”, ничего не пишется поверх. Это значит, что база помнит все ревизии документов до тех пор пока не будет выполнена операция очистки/оптимизации. Также это значит, что база выжимает из SSD-дисков всё, на что они способны – и при этом их бережёт.
Как связаны append only и SSD? Я понимаю, почему SSD хороши для random reads (в любых базах), но для append-only как бы без разницы, какой диск, HDD прекрасно справляются с последовательной записью.
no subject
Я, конечно, не настоящий С.-сварщик, но суть, полагаю, передал верно.
no subject
no subject
А так - да, это не единственный неправильный шаг на том этапе жизни их продукта, они это и не отрицали. Сейчас зато у тех ребят все Ok, нашли решение под себя, и им норм.
no subject
Может не слишком удачно прозвучало, я ничего не хотел сказать, просто описал то, что вижу вокруг себя. Понятно, что мое восприятие искажено просто тем, что оно неполное, поэтому воспринимать это нужно просто как еще один «репортаж с места».
Да и в целом у меня не было цели облить грязью CouchDB, просто увидел обзор и решил дополнить тем, что знаю. Мне кажется, всегда полезно иметь как можно более полную картину, как оно внутри устроено и к каким ограничениям приводит. Просто не хочется, чтобы кто-то выбрал CouchDB для задачи, к которой он не подходит из-за своих ограничений. Понятно, что есть миллион задач, где это абсолютно прекрасный выбор. И я в целом рад, что ты его нашел и делаешь на нем крутые штуки, мне кажется, такие вещи расширяют представление о диапазоне возможных архитектур, что всегда хорошо.
no subject
no subject
Насчёт кластеров и всего остального – http://bigcouch.cloudant.com/, эти фичи попадут в один из ближайших официальных релизов.
Optimistic replication предназначена больше для распространения данных, а не для поддержания гарантированной синхронности всех узлов кластера. Если структура сети обмена заранее неизвестна, это единственный реально рабочий механизм. А если вы строите всамделишные открытые распределённые системы, вам топология заранее не известна никогда.
Технологии offline first – как раз пример таких систем. И в этой нише я вообще не вижу никаких вариантов кроме CouchDB (или PouchDB, если вам надо нормальную БД в браузере).
----
HDD прекрасно справляется с последовательной записью, если удаётся выделить непрерывный кусок размером с записываемые данные. Это может быть проблематично, если мы, скажем, впервые считаем большой индекс или пишем сразу пачку документов (реплицируем). SSD, понятно, такой проблемы не имеет. Я мерял, чего это стоит в циферках при разных условиях – очень впечатляющая разница, всегда минимум кратная.
----
CouchBase – это, в общем, CouchDB в памяти, без аттачей и REST. Интересно, что он быстрее (правда, и тяжелее), например, Redis’а.
no subject
Тем не менее, важно понимать, что проблемы с компактом возникают тогда, когда система, работающая на CouchDB, неверно спроектирована и использует CouchDB вместо memcache или rdbms.
Например, нам надо считать хиты юзера по урлам.
А) Мы можем быть дураками и обновлять документ профиля юзера на каждый хит – и получить взрыв мусора.
Б) Мы можем писать новый док на каждый хит, а потом их коллэйтить и считать map/reduce’ом.
(План Б тоже не очень, потому что нагруженные логи лучше делать SQL-ной базой или редисом там.)
Ещё пример. Мы хотим хранить посты и комменты. Не зная про append-only кажется, что раз комменты обычно не смотрят отдельно от постов, разумно их дописывать прямо в документ поста из соображений целостности и скорости выборки. Это, конечно, иллюзия.