Настройка CockroachDB для веб-приложения
CockroachDB — распределённая SQL-база, совместимая с PostgreSQL-протоколом. Горизонтальное масштабирование без шардирования руками, автоматическая репликация данных и multi-region deployments — это то, чего не умеет стандартный PostgreSQL без серьёзных дополнений. Если приложение уже использует Postgres-драйверы, переключение на CockroachDB минимально по коду.
Когда CockroachDB имеет смысл
Глобальные приложения с пользователями в нескольких регионах, где нужна низкая latency везде. Системы, которые нельзя останавливать — CockroachDB переживает потерю нод без downtime. Масштабирование записи горизонтально — стандартный Postgres этого не умеет. Compliance-требования с хранением данных в конкретном регионе.
Установка (single-node для разработки)
wget -qO - https://binaries.cockroachdb.com/cockroach-latest.linux-amd64.tgz | tar xz
mv cockroach-*/cockroach /usr/local/bin/
# Запуск без SSL для dev
cockroach start-single-node --insecure --background \
--store=/var/lib/cockroachdb \
--listen-addr=localhost:26257 \
--http-addr=localhost:8080 \
--log-dir=/var/log/cockroachdb
Создание базы:
cockroach sql --insecure
CREATE DATABASE myapp;
CREATE USER myapp WITH PASSWORD 'strong_password';
GRANT ALL ON DATABASE myapp TO myapp;
Production кластер (три ноды)
# На каждой ноде — генерация сертификатов
cockroach cert create-ca --certs-dir=/etc/cockroachdb/certs --ca-key=/etc/cockroachdb/certs/ca.key
cockroach cert create-node 10.0.0.1 localhost $(hostname) --certs-dir=/etc/cockroachdb/certs --ca-key=/etc/cockroachdb/certs/ca.key
cockroach cert create-client root --certs-dir=/etc/cockroachdb/certs --ca-key=/etc/cockroachdb/certs/ca.key
# Запуск ноды 1
cockroach start \
--certs-dir=/etc/cockroachdb/certs \
--advertise-addr=10.0.0.1 \
--join=10.0.0.1,10.0.0.2,10.0.0.3 \
--store=/var/lib/cockroachdb \
--background
# После запуска всех нод — инициализация кластера
cockroach init --certs-dir=/etc/cockroachdb/certs --host=10.0.0.1
Схема и миграции
Синтаксис практически идентичен PostgreSQL:
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email STRING NOT NULL UNIQUE,
name STRING NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE orders (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id),
status STRING NOT NULL DEFAULT 'pending',
total DECIMAL(10,2) NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
INDEX idx_orders_user (user_id, created_at DESC),
INDEX idx_orders_status (status, created_at DESC)
);
CockroachDB использует UUIDs как PK по умолчанию — sequential integers создают hotspots на одной ноде.
Multi-region настройка
-- Включить geo-партиционирование
ALTER DATABASE myapp SET PRIMARY REGION 'eu-central-1';
ALTER DATABASE myapp ADD REGION 'us-east-1';
ALTER DATABASE myapp ADD REGION 'ap-southeast-1';
-- Таблица пользователей с региональной привязкой
ALTER TABLE users SET LOCALITY REGIONAL BY ROW;
-- После этого каждый ряд хранится ближе к пользователю
-- crdb_region определяет ближайший регион
Подключение из Node.js
CockroachDB работает с любым PostgreSQL-драйвером:
import { Pool } from 'pg'
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
// DATABASE_URL = postgresql://myapp:[email protected]:26257/myapp?sslmode=require
max: 25,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 5000,
})
// CockroachDB рекомендует retry логику для serializable транзакций
async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn()
} catch (err: any) {
// 40001 — serialization failure (транзакция требует повтора)
if (err.code === '40001' && attempt < maxRetries - 1) {
const delay = Math.min(100 * Math.pow(2, attempt), 2000)
await new Promise(r => setTimeout(r, delay + Math.random() * 100))
continue
}
throw err
}
}
throw new Error('max retries exceeded')
}
// Транзакция с повторами
async function transferFunds(fromId: string, toId: string, amount: number) {
return withRetry(async () => {
const client = await pool.connect()
try {
await client.query('BEGIN')
const { rows: [from] } = await client.query(
'SELECT balance FROM accounts WHERE id = $1 FOR UPDATE', [fromId]
)
if (from.balance < amount) throw new Error('insufficient funds')
await client.query(
'UPDATE accounts SET balance = balance - $1 WHERE id = $2', [amount, fromId]
)
await client.query(
'UPDATE accounts SET balance = balance + $1 WHERE id = $2', [amount, toId]
)
await client.query('COMMIT')
} catch (e) {
await client.query('ROLLBACK')
throw e
} finally {
client.release()
}
})
}
Мониторинг через встроенный UI
# DB Console доступна на порту 8080
# Ключевые разделы:
# - Statements: топ запросов по времени выполнения
# - Network Latency: latency между нодами
# - Replication: статус репликации ренджей
# CLI мониторинг
cockroach node status --certs-dir=/etc/cockroachdb/certs --host=10.0.0.1
cockroach debug zip debug.zip --certs-dir=/etc/cockroachdb/certs --host=10.0.0.1
Бэкапы
-- Полный бэкап в S3
BACKUP INTO 's3://my-bucket/cockroachdb-backups?AWS_ACCESS_KEY_ID=...&AWS_SECRET_ACCESS_KEY=...'
AS OF SYSTEM TIME '-10s';
-- Инкрементальный
BACKUP INTO LATEST IN 's3://my-bucket/cockroachdb-backups?...';
-- Расписание
CREATE SCHEDULE daily_backup
FOR BACKUP INTO 's3://my-bucket/cockroachdb-backups?...'
RECURRING '@daily'
FULL BACKUP ALWAYS;
Сроки
Настройка трёхузлового кластера в одном регионе с настройкой мониторинга: 2–3 дня. Конфигурация multi-region с geo-партиционированием: 3–5 дней. Миграция из PostgreSQL (схема, данные, приложение, тестирование под нагрузкой): 1–2 недели.







