Поднимаем кластер CockroachDB из трех нод

12 февраля 2020

CockroachDB — это распределенная РСУБД, написанная на Go. Является представителем так называемых NewSQL баз данных, которые пытаются совместить в себе горизонтальную масштабируемость и высокую доступность NoSQL решений с интерфейсом (SQL) и строгостью (ACID) традиционных РСУБД. Помимо прочего, CockroachDB интересен тем, что реализует протокол PostgreSQL, что упрощает портирование на него существующих приложений. Давайте же попробуем поднять свой кластер CockroachDB и поработать с ним.

Предварительные шаги

Для экспериментов было создано три дроплета (VDS) в горячо любимом мной DigitalOcean. Приведенная ссылка является реферальной. Что она дает описано в FAQ.

Дроплеты получились следующими:

Droplet Name    Internal IP
------------    ------------
cockroach1      10.129.1.14
cockroach2      10.129.1.54
cockroach3      10.129.0.228

Между дроплетами был включен private networking. В качестве ОС была использована Ubuntu Linux 18.04 LTS.

На каждом из VDS выполняем следующие шаги. Качаем апдейты:

apt update
apt upgrade

Документация на CockroachDB рекомендует поставить NTP. Не вижу причин этого не сделать:

apt install ntp
ntpq -pn

Чтобы постоянно не сидеть под рутом, создаем пользователя с правом на sudo:

adduser eax
usermod -a -G sudo eax
mkdir /home/eax/.ssh
cp /root/.ssh/authorized_keys /home/eax/.ssh/
chown -R eax:eax /home/eax

Ребутаемся:

shutdown -r now

Теперь мы готовы перейти к следующему этапу.

Обратите внимание, что в рамках этой статьи не рассматривается настройка фаервола. Отмечу лишь, что CockroachDB использует всего два порта. На TCP-порту 8080 живет его веб-интерфейс. Через TCP-порт 26257 происходит общение между нодами, а также между нодами и клиентами по протоколу PostgreSQL.

Далее будет рассмотрена так называемая insecure конфигурация CockroachDB. Она предполагает, что весь ваш кластер работает в относительно доверенном окружении. Если вам нужна конфигурация с шифрованием, сертификатами и вот этой всей историей, обращайтесь к официальной документации.

Установка CockroachDB

На момент написания статьи последней стабильной версией CockroachDB была v19.2.2, на которой и проводились эксперименты. К моменту, когда вы будете читать эти строки, данная версия может потерять актуальность, и шаги по установке могут измениться. Самую свежую информацию вы всегда найдете на официальном сайте проекта.

Повторяем на всех трех машинах:

wget https://binaries.cockroachdb.com/cockroach-v19.2.2.linux-amd64.tgz
tar -xvzf cockroach-v19.2.2.linux-amd64.tgz
sudo cp cockroach-v19.2.2.linux-amd64/cockroach /usr/local/bin

sudo mkdir /var/lib/cockroach
sudo useradd cockroach
sudo chown cockroach /var/lib/cockroach

Берем шаблон сервиса отсюда. В нем --advertise-addr= нужно заменить на внутренний IP-адрес машины, а список --join= указать пустой для первой ноды, внутренний IP 1-ой ноды для второй ноды, и адреса 1-ой и 2-ой ноду для третьей. Результат сохраняем в /etc/systemd/system/cockroachdb.service.

Далее:

sudo systemctl enable cockroachdb
sudo systemctl start cockroachdb
sudo systemctl status cockroachdb

Получить доступ к веб-интерфейсу CockroachDB проще всего через ssh port forwarding:

LocalForward 8081 10.129.1.14:8080

Вот так он примерно выглядит (кликабельно, PNG 3072x1920, 573 Кб):

Веб-интерфейс CockroachDB

Из веб-интерфейса можно узнать текущее состояние нод, посмотреть статистику по таблицам, динамические графики по разным типам запросов (SELECT’ы, UPDATE’ы, …) и так далее.

Поздравляю, кластер настроен!

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

Для подключения к РСУБД выполняем команду:

cockroach sql --insecure

Далее говорим, например:

CREATE DATABASE phonebook;
CREATE USER IF NOT EXISTS phonebook;
GRANT ALL ON DATABASE phonebook TO phonebook;
SET DATABASE = phonebook;
CREATE TABLE phonebook(id SERIAL PRIMARY KEY,
                       name VARCHAR(64), phone VARCHAR(64));
INSERT INTO phonebook (name, phone) VALUES ('Alice', '123');
INSERT INTO phonebook (name, phone) VALUES ('Bob', '456');
SELECT * FROM phonebook;
INSERT INTO phonebook(name,phone)
  SELECT 'user_' || n :: TEXT, '100' || n :: TEXT
    FROM generate_series(1,10000) AS n;
DROP TABLE phonebook;

В целом — все почти как в PostgreSQL. В том числе, есть команды \l, \d, \q и \?. Команда \c (подключение к базе данных) почему-то не реализована, но вместо нее есть SET DATABASE. Также, для тех, кто до этого работал с MySQL, поддерживаются команды SHOW DATABASES и SHOW TABLES. Автокомплит по именам таблиц и столбцов пока не реализован. Интересно, что в отличие от PostgreSQL, SERIAL PRIMARY KEY генерируются длинные и не последовательные:

root@:26257/phonebook> select * from phonebook;
          id         | name  | phone
+--------------------+-------+-------+
  528163249051893761 | Alice | 123
  528163277677395969 | Bob   | 456
(2 rows)

После небольших доработок мне удалось запустить на CockroachDB пример микросерсиса на Go и pgx. В процессе было выявлено еще несколько отличий от PostgreSQL. Во-первых, в CockroachDB не реализован pg_advisory_lock(), на котором часто реализуется автоматическая миграция схемы базы данных. Решение заключается в том, чтобы выполнять миграцию в одну большую транзакцию (само собой разумеется, с ретраями).

Fun fact! Транзакции в CockroachDB всегда исполняются на уровне изоляции serializable. Еще вам может быть интересно узнать, что для хранения всех данных используется RocksDB.

Во-вторых, CockroachDB не понимает постгресовый синтаксис BEGIN ... [ NOT ] DEFERABLE:

root@:26257/phonebook> begin isolation level serializable
                    ->   read write not deferable;
invalid syntax: statement ignored: at or near "not": syntax error
DETAIL: source SQL:
begin isolation level serializable read write not deferable
                                              ^
HINT: try \h BEGIN

При портировании / разработке приложения на CockroachDB необходимо убедиться, что оно не использует данный синтаксис.

Каких-то других проблем при портировании сервиса, вроде, не было. Помню, что мне пригодилась возможность включать и выключать логирование запросов:

SET CLUSTER SETTING sql.trace.log_statement_execute = true;
SET CLUSTER SETTING sql.trace.log_statement_execute = false;

Когда логирование включено, говорим:

tail -f /var/lib/cockroach/cockroach-data/logs/cockroach-sql-exec.log

В файле вы увидите все SQL-запросы к CockroachDB и сообщения об ошибках, если они возникают.

Разработка и тестирование

CockroachDB можно запустить локально в Docker таким образом:

docker run -d --name cockroach -p 5432:26257 -p 8080:8080 \
  cockroachdb/cockroach:v19.2.3 start-single-node --insecure

Подключение к СУБД:

docker exec -it cockroach ./cockroach sql --insecure

Контейнеры могут быть использованы для тестирования приложения с помощью dockertest, как раньше мы это делали для PostgreSQL. Полный пример приложения вместе с тестами к нему вы найдете в этом репозитории на GitHub.

Заключение

В первом приближении выглядит так, как если бы все работало. Безусловно, перед тем, как выкатывать CockroachDB на прод, нужно пройти полный цикл тестирования приложения, с альфа- и бета-периодами, и вот этим вот всем. Но если вы не завязаны на какие-то PostgreSQL-специфичные возможности (полнотекстовый поиск, PostGIS, самописные расширения), а также уверены, что они вам не понадобятся, то особых проблем возникнуть не должно.

Следует однако иметь ввиду, что на момент написания этих строк транзакции в CockroachDB имели ряд известных ограничений. Также не внушает энтузиазма список issues на GitHub. Наконец, следует знать, что некоторые фичи CockroachDB отсутствуют в открытой версии и включены только в CockroachDB Enterprise и CockroachCloud. Среди таких фичей — снятие бэкапов.

Как мне кажется, CockroachDB может быть интересным решением для тех, кому нужно масштабировать СУБД на сотни машин, и сделать это ручным шардированием либо слишком дорого, либо крайне сложно в силу специфики приложения. Во всех остальных случаях PostgreSQL подойдет лучше, как более универсальная, проверенная временем и знакомая многим РСУБД.

Метки: , .


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