О нас Руководства Проекты Контакты
Админка
пожалуйста подождите

Введение

Репликация базы данных обеспечивает долговечность и доступность данных за счёт поддержания копий на нескольких серверах. Для production-систем репликация не является опциональной — она необходима для аварийного восстановления, масштабирования чтения и выполнения обслуживания без простоя. В этом руководстве рассматриваются практические стратегии репликации для PostgreSQL и MySQL.

Концепции репликации

Типы репликации

Physical Replication: копирует точные байты базы данных. Быстро, но реплики должны быть на идентичных версиях PostgreSQL.

Logical Replication: копирует логические изменения (SQL-операции). Более гибко, допускает разные версии и выборочную репликацию.

Synchronous vs Asynchronous:

  • Synchronous: primary ждёт подтверждения от replica. Потери данных нет, но выше задержка.
  • Asynchronous: primary не ждёт. Лучшая производительность, но возможна потеря данных.

Потоковая репликация PostgreSQL (Streaming Replication)

Конфигурация primary-сервера

# postgresql.conf на primary
# Включить архивацию WAL
wal_level = replica
max_wal_senders = 10
wal_keep_size = 1GB
# Для synchronous replication (опционально)
synchronous_standby_names = 'replica1'
# pg_hba.conf — разрешить подключения для репликации
host replication replicator 192.168.1.0/24 md5

Создайте пользователя для репликации:

CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'secure_password';

Настройка replica-сервера

# Остановить PostgreSQL на replica
sudo systemctl stop postgresql
# Удалить существующие данные
rm -rf /var/lib/postgresql/14/main/*
# Скопировать с primary с помощью pg_basebackup
pg_basebackup -h primary.example.com -U replicator -D /var/lib/postgresql/14/main -P -R
# Флаг -R создаёт standby.signal и настраивает подключение
# postgresql.conf на replica
# Подключение к primary
primary_conninfo = 'host=primary.example.com port=5432 user=replicator password=secure_password'
# Запустить replica
sudo systemctl start postgresql

Проверка репликации

-- На primary: проверить статус репликации
SELECT client_addr, state, sent_lsn, write_lsn, replay_lsn
FROM pg_stat_replication;
-- На replica: проверить статус recovery
SELECT pg_is_in_recovery();
SELECT pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn();

Логическая репликация PostgreSQL (Logical Replication)

Publisher (Source)

# postgresql.conf
wal_level = logical
max_replication_slots = 4
max_wal_senders = 4
-- Создать publication
CREATE PUBLICATION my_publication FOR TABLE users, orders;
-- Или для всех таблиц
CREATE PUBLICATION full_publication FOR ALL TABLES;

Subscriber (Target)

-- Создать subscription
CREATE SUBSCRIPTION my_subscription
CONNECTION 'host=publisher.example.com dbname=mydb user=replicator password=secure'
PUBLICATION my_publication;
-- Проверить статус
SELECT * FROM pg_stat_subscription;

Репликация MySQL

Конфигурация primary

# my.cnf на primary
[mysqld]
server-id = 1
log_bin = mysql-bin
binlog_format = ROW
binlog_do_db = mydb
-- Создать пользователя для репликации
CREATE USER 'replicator'@'%' IDENTIFIED BY 'secure_password';
GRANT REPLICATION SLAVE ON *.* TO 'replicator'@'%';
FLUSH PRIVILEGES;
-- Получить позицию binary log
SHOW MASTER STATUS;
-- Примечание: значения File и Position

Конфигурация replica

# my.cnf на replica
[mysqld]
server-id = 2
relay_log = mysql-relay-bin
read_only = 1
-- Настроить репликацию
CHANGE MASTER TO
MASTER_HOST='primary.example.com',
MASTER_USER='replicator',
MASTER_PASSWORD='secure_password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
-- Запустить репликацию
START SLAVE;
-- Проверить статус
SHOW SLAVE STATUS\G

Стратегии failover

Ручной failover (PostgreSQL)

-- На replica: повысить до primary
SELECT pg_promote();
-- Или через командную строку
pg_ctl promote -D /var/lib/postgresql/14/main

Обновите строки подключения приложения, чтобы они указывали на новый primary.

Автоматический failover с Patroni

Patroni управляет высокой доступностью PostgreSQL с автоматическим failover.

# patroni.yml
scope: postgres-cluster
name: node1
restapi:
listen: 0.0.0.0:8008
connect_address: node1.example.com:8008
etcd:
hosts: etcd1:2379,etcd2:2379,etcd3:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
postgresql:
use_pg_rewind: true
parameters:
max_connections: 100
postgresql:
listen: 0.0.0.0:5432
connect_address: node1.example.com:5432
data_dir: /var/lib/postgresql/14/main
authentication:
replication:
username: replicator
password: secure_password
superuser:
username: postgres
password: postgres_password

HAProxy для маршрутизации подключений

# haproxy.cfg
frontend postgres_frontend
bind *:5432
default_backend postgres_backend
backend postgres_backend
option httpchk GET /master
http-check expect status 200
server node1 node1:5432 check port 8008
server node2 node2:5432 check port 8008
server node3 node3:5432 check port 8008

Масштабирование чтения с помощью реплик

Разделение чтения/записи на уровне приложения

// Пример для Laravel
// config/database.php
'pgsql' => [
'read' => [
'host' => [
'replica1.example.com',
'replica2.example.com',
],
],
'write' => [
'host' => 'primary.example.com',
],
'driver' => 'pgsql',
'database' => 'mydb',
// ...
],
// Принудительно использовать подключение для записи для критичных чтений
$user = DB::connection('pgsql')->select('SELECT * FROM users WHERE id = ?', [1]);

Пулинг подключений с read replicas

# PgBouncer с несколькими backends
[databases]
mydb = host=primary.example.com port=5432
mydb_ro = host=replica1.example.com,replica2.example.com port=5432

Мониторинг репликации

Задержка репликации PostgreSQL

-- На primary: проверить lag по каждой replica
SELECT client_addr,
pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS lag_bytes,
pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) / 1024 / 1024 AS lag_mb
FROM pg_stat_replication;
-- На replica: проверить lag
SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp())) AS lag_seconds;

Задержка репликации MySQL

SHOW SLAVE STATUS\G
-- Ищите: Seconds_Behind_Master

Пороговые значения для оповещений

  • Warning: задержка > 10 секунд
  • Critical: задержка > 60 секунд
  • Emergency: replica отключена

Резервное копирование с использованием реплик

Делайте бэкапы с реплик, чтобы не влиять на primary:

# PostgreSQL — бэкап с replica
pg_dump -h replica.example.com -U postgres mydb > backup.sql
# Или physical backup
pg_basebackup -h replica.example.com -U replicator -D /backup -P

Лучшие практики

  1. Используйте synchronous replication для критичных данных (как минимум одна replica).
  2. Непрерывно мониторьте задержку репликации.
  3. Регулярно тестируйте failover в non-production.
  4. Размещайте реплики в разных availability zones.
  5. Документируйте процедуры failover.
  6. Автоматизируйте failover там, где это возможно (Patroni, orchestrator).
  7. Используйте connection pooling для эффективного управления подключениями.

Заключение

Репликация базы данных обеспечивает основу для высокой доступности и аварийного восстановления. Начните с асинхронной потоковой репликации для масштабирования чтения, добавьте synchronous replication для критичных данных и внедрите автоматический failover для production-систем. Регулярное тестирование гарантирует, что ваши процедуры failover сработают, когда это потребуется.

 
 
 
Языки
Темы
Copyright © 1999 — 2026
Зетка Интерактив