CouchDB — документная база данных, которая общается по HTTP и хранит JSON. Её главная особенность — встроенная репликация: две базы синхронизируются напрямую, без промежуточного сервера и без общей сети. Это удобно для распределённых приложений, офлайн-клиентов и обмена данными между площадками. Разберём установку, ревизии, репликацию, конфликты и обслуживание кластера.

Модель данных

База — это набор документов. Каждый имеет _id и _rev; ревизия меняется при каждом обновлении. Старые версии не удаляются сразу, а становятся недоступными, пока их не соберёт компактизация. Такая модель MVCC позволяет читать без блокировок.

Схемы нет: структура документа произвольна, а индексы описываются в design documents. Запросы идут либо через Mango, либо через map-reduce-вьюхи, которые пересчитываются инкрементально. База хорошо ложится на SSD и не требует сложного тюнинга.

Установка

В Debian и Ubuntu пакет ставят из репозитория Apache. После установки сервис слушает 5984, а Fauxton доступен по /_utils. Порт нельзя открывать в интернет без TLS и аутентификации.

sudo apt install couchdb
sudo systemctl enable --now couchdb
C=http://127.0.0.1:5984
curl -s $C/_up

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

docker run -d --name couchdb -p 5984:5984 \
  -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=secret \
  -v couchdb_data:/opt/couchdb/data couchdb:3

Одиночный узел и кластер

После установки кластер состоит из одного узла, но настройка не завершена. Команда _cluster_setup с action enable_single_node создаёт системные базы и включает режим. Без неё часть служебных запросов возвращает ошибки.

Для кластера узлы объединяют действием add_node, а cookie в /opt/couchdb/.erlang.cookie должен совпадать на всех машинах. Число шардов q и реплик n задают в local.ini до создания баз.

curl -X POST -u admin:secret $C/_cluster_setup \
  --json '{"action":"enable_single_node"}'
curl -s -u admin:secret $C/_membership

Документы и ревизии

Создание — POST на адрес базы, обновление — PUT с текущей ревизией. Если ревизия устарела, сервер вернёт 409 Conflict: это не ошибка, а защита от перезаписи чужих изменений.

Для массовой загрузки есть _bulk_docs, для чтения — _all_docs. Обновлять документ без _rev нельзя: CouchDB не поддерживает «последний победил» на уровне API.

curl -X PUT -u admin:secret $C/notes
curl -X POST -u admin:secret $C/notes --json '{"title":"Первый"}'
curl -s -u admin:secret "$C/notes/_all_docs?limit=5"

Запросы: Mango и вьюхи

Mango хорош для простых выборок: селектор описывает условия, поля ограничивают вывод, индекс создаётся отдельно. Без индекса база предупредит, что запрос будет медленным.

Вьюхи нужны для агрегатов и запросов, которые Mango не выражает. Map-функция эмитит ключ и значение, reduce сворачивает результат. Вьюха живёт в design document и обновляется при чтении, если не включён stale=ok.

curl -X POST -u admin:secret $C/notes/_find \
  --json '{"selector":{"year":{"$gt":2020}}}'
curl -s -u admin:secret "$C/notes/_design/reports/_view/by_year"

Репликация

Репликация запускается запросом _replicate с source и target. Она бывает одноразовой или continuous; во втором случае сервер держит процесс и повторяет попытки после обрыва. Документ в базе _replicator переживает перезапуск, а разовый вызов — нет.

Фильтры позволяют передавать не всё: функция в design document решает, какие документы попадут в поток. Это экономит трафик между площадками, но фильтр должен быть детерминированным.

curl -X POST -u admin:secret $C/_replicate \
  --json '{"source":"notes","target":"http://admin:secret@backup:5984/notes"}'

Конфликты

При записи в две реплики одной ревизии появляются конфликтующие ветви. CouchDB не удаляет их автоматически: выигравшая версия видна в документе, остальные доступны по conflicts=true. Разрешение — удалить проигравшие ревизии или собрать из них новую версию.

Стратегию выбирают заранее. Для справочников подходит «побеждает старший по времени», для заказов — слияние полей и ручная проверка. Автоматическое удаление без разбора теряет данные.

curl -s -u admin:secret "$C/notes/docid?conflicts=true"
curl -X DELETE -u admin:secret "$C/notes/docid?rev=2-abc"

Безопасность

Администратор задаётся в секции [admins] файла local.ini; пароль в открытом виде допустим только при первой записи, при старте он хешируется. Для приложений создают отдельных пользователей и базы с ограниченными правами.

require_valid_user закрывает анонимный доступ целиком. TLS настраивают в секции [ssl], а порты 4369 и диапазон 9100–9200 оставляют только во внутренней сети: это служебный трафик Erlang.

[chttpd]
bind_address = 127.0.0.1
require_valid_user = true

[admins]
admin = strongpassword

Обслуживание

Компактизация переписывает файлы базы и удаляет старые ревизии. Запускают её вручную или по расписанию; вьюхи компактизируются отдельно. Без этого диск растёт, а чтение замедляется.

Резервная копия — это реплика на другой сервер или снимок каталога данных. Снимок делают на остановленном узле или средствами файловой системы, когда репликация завершена. Реплика спасает от сбоя узла, но не от ошибочного удаления: purge разносится по репликам.

curl -X POST -u admin:secret $C/notes/_compact
curl -s -u admin:secret "$C/_dbs_info?descending=true"

Диагностика

Логи идут в journalctl -u couchdb или в файл, если запуск не через systemd. _active_tasks показывает репликации, индексацию и компактизацию; зависшая задача видна там же.

  • 401 — неверный пароль или включён require_valid_user;
  • 409 — устаревшая ревизия, перечитайте документ;
  • 500 при репликации — проверьте cookie и доступность портов;
  • медленные вьюхи — не хватает индекса или идёт холодная сборка.
journalctl -u couchdb -n 100 --no-pager
curl -s -u admin:secret $C/_up
curl -s -u admin:secret $C/_active_tasks

Чек-лист

  • задан администратор и закрыт анонимный доступ;
  • выполнен enable_single_node или настроен кластер;
  • порты 4369 и 9100–9200 закрыты снаружи;
  • настроены компактизация и мониторинг диска;
  • есть проверенная реплика или снимок данных;
  • описана стратегия разрешения конфликтов.

Итог

CouchDB сильна там, где нужна синхронизация между узлами и простое HTTP-взаимодействие. Ревизии и конфликты — не баг, а часть модели, и приложение должно уметь с ними работать.

Начните с одного узла, проверьте репликацию на тестовой базе и только потом переходите к кластеру. Тогда конфликты и потери данных не станут неожиданностью в продакшене.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте