PostgreSQL es un sistema de gestión de bases de datos relacionales (RDBMS) potente y rico en funciones. Es gratuito y de código abierto, y ha estado en desarrollo desde 1996. Postgres ofrece diferentes formas de archivar y replicar datos, una de las cuales es la replicación de transmisión. En este modo, una instancia primaria (maestra) maneja la base de datos activa principal y ejecuta operaciones. La instancia secundaria (esclava) copia todos los cambios de la instancia principal, manteniendo una copia idéntica de la base de datos activa. El servidor secundario también puede aceptar consultas de solo lectura. Si el servidor principal falla, el servidor secundario puede salir del modo de espera y funcionar como el nuevo maestro (esto se denomina conmutación por error).
La replicación de PostgreSQL generalmente se basa en el registro de escritura anticipada (WAL), el proceso de registrar cambios en los datos antes de escribirlos en el disco. Luego, estos registros WAL se copian en un segundo nodo como archivos (envío de registros basado en archivos) o se transmiten directamente entre nodos (replicación de transmisión). En la mayoría de los casos, esto último reduce la demora para que los cambios en el nodo principal sean recibidos por el nodo en espera.
El problema con el uso de la replicación de transmisión sin trasvase de registros basado en archivos es que el servidor secundario puede perder algunos registros WAL si el servidor principal los descarta demasiado pronto. Varios parámetros de configuración pueden reducir este riesgo, pero a menudo conllevan un costo de almacenamiento innecesario. La solución son las ranuras de replicación, una función proporcionada por Postgres que garantiza que el servidor principal solo descarte los registros WAL después de que los haya recibido el nodo en espera.
Configuraremos la replicación de transmisión con ranuras de replicación en dos nodos de Debian 10.
Requisitos
- Dos instancias idénticas de Debian 10.
- Acceso raíz a ambas instancias.
- La variable de entorno $EDITOR debe establecerse en ambas instancias.
Paso 1:Instalación de PostgreSQL
Actualice y reinicie ambos nodos:
apt update apt upgrade -y reboot
Instale Postgres en ambos nodos y asegúrese de que PostgreSQL esté habilitado y ejecutándose:
apt install -y postgresql systemctl enable --now [email protected]
NOTA:Al actualizar PostgreSQL, actualizar primero el standby es la opción más segura según su documentación.
Paso 2:Configuración inicial
De forma predeterminada, PostgreSQL solo escucha en la interfaz de bucle invertido y no es accesible desde el exterior. Cambie la dirección de escucha en ambos nodos editando postgresql.conf:
$EDITOR /etc/postgresql/11/main/postgresql.conf
Busque la siguiente línea:
#listen_addresses = 'localhost'
Cámbialo por:
listen_addresses = 'node_ip_address,127.0.0.1'
Si ambos nodos comparten la misma red local, puede usar direcciones privadas para node_ip_address, aunque no se podrá acceder a Postgres por Internet. De lo contrario, utilice direcciones públicas.
Guarde el cambio y luego reinicie ambas instancias:
systemctl restart [email protected]
Paso 3:Configuración maestra
Este paso solo se aplica al servidor primario/maestro.
Abra la terminal de Postgres:
sudo -u postgres psql
El nodo en espera utilizará un usuario para conectarse al maestro. Créalo:
postgres=# CREATE ROLE replicator LOGIN REPLICATION ENCRYPTED PASSWORD 'replicator_password';
Luego cree una ranura de replicación y salga:
postgres=# SELECT * FROM pg_create_physical_replication_slot('replicator'); postgres=# \q
En aras de la simplicidad, la función de replicación y la ranura se denominan "replicador", aunque no tienen que ser idénticos.
A continuación, cree una entrada en pg_hba.conf para permitir que el usuario del replicador se conecte del modo de espera al maestro. Ábrelo:
$EDITOR /etc/postgresql/11/main/pg_hba.conf
Agregue la siguiente línea al final:
host replication replicator standby_ip_address/32 md5
Reinicie la instancia maestra:
systemctl restart [email protected]
Paso 4:Copia de seguridad base
Los comandos de este paso deben ejecutarse en el servidor secundario/esclavo.
Primero, detenga Postgres en el nodo secundario:
systemctl stop [email protected]
Copia de seguridad del directorio de datos anterior:
mv /var/lib/postgresql/11/main/ /var/lib/postgresql/11/main.bak
Use el siguiente comando para clonar el directorio de datos del maestro al esclavo:
pg_basebackup -h master_ip_address -U replicator -D /var/lib/postgresql/11/main/ -P --password --slot replicator
Se te solicitará una contraseña. Ingrese la contraseña que eligió para el rol de replicador durante su creación en el maestro. Una vez que se complete la transferencia, otorgue la propiedad del directorio de datos al usuario de postgres:
chown -R postgres:postgres /var/lib/postgresql/11/main
Paso 5:Configuración en espera
Este paso solo se aplica al servidor secundario/esclavo.
Habilite el modo de espera activo en postgresql.conf:
$EDITOR /etc/postgresql/11/main/postgresql.conf
Busque y descomente la siguiente línea:
#hot_standby = on
Cree el archivo recovery.conf en el directorio de datos de Postgres:
$EDITOR /var/lib/postgresql/11/main/recovery.conf
Habilitar el modo de espera:
standby_mode = 'on'
Establezca los parámetros de conexión de replicación utilizando las credenciales creadas en el maestro:
primary_conninfo = 'host=master_ip_address port=5432 user=replicator password=replicator_password'
Establezca el nombre de la ranura de replicación que ha creado en el maestro:
primary_slot_name = 'replicator'
Establezca la ruta a un archivo de activación de conmutación por error:
trigger_file = '/var/lib/postgresql/11/main/failover.trigger'
Si se establece el parámetro trigger_file, Postgres saldrá del modo de espera e iniciará el funcionamiento normal como servidor principal cuando se cree este archivo de activación. Este parámetro no es obligatorio.
Después de crear recovery.conf, otorgue la propiedad al usuario de postgres:
chown postgres:postgres /var/lib/postgresql/11/main/recovery.conf
Ahora puede iniciar Postgres:
systemctl start [email protected]
Ahora está en modo de espera y debería estar replicando cualquier transacción nueva.
Prueba
Prueba de replicación
Para probar la replicación, realice cualquier acción de escritura en el maestro. Por ejemplo, cree una nueva base de datos en el maestro:
sudo -u postgres psql -c "CREATE DATABASE replitest"
Espere unos segundos y luego enumere las bases de datos en el esclavo:
sudo -u postgres psql -c "\l"
Debería ver que la base de datos de repetición fue efectivamente replicada por el servidor en espera:
List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+-------------+-------------+----------------------- postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | replitest | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres (4 rows)
Prueba de conmutación por error
NOTA:Probar la conmutación por error como se muestra aquí requerirá reiniciar el servidor en espera después de la conmutación por error.
Dado que Postgres está en modo de espera, no debería poder realizar ninguna operación de escritura en el nodo secundario antes de la conmutación por error. Por ejemplo, ejecute el siguiente comando:
sudo -u postgres psql -c "CREATE DATABASE test"
El comando debería fallar:
ERROR: cannot execute CREATE DATABASE in a read-only transaction
Para señalar la conmutación por error, cree el archivo desencadenante especificado en recovery.conf
touch /var/lib/postgresql/11/main/failover.trigger
Espere unos segundos, luego intente realizar una operación de escritura. Por ejemplo:
sudo -u postgres psql -c "CREATE DATABASE test2"
Dado que Postgres ya no está funcionando en espera, la operación se realizará correctamente. Postgres también cambiará el nombre de su archivo recovery.conf a recovery.done y eliminará el archivo activador.
Para volver al modo de espera, detenga Postgres en el (antiguo) nodo secundario:
systemctl stop [email protected]
Restablecer el directorio de datos:
mv /var/lib/postgresql/11/main/ /var/lib/postgresql/11/main.2.bak pg_basebackup -h master_ip_address -U replicator -D /var/lib/postgresql/11/main/ -P --password --slot replicator chown -R postgres:postgres /var/lib/postgresql/11/main
Y vuelva a crear recovery.conf:
cp /var/lib/postgresql/11/main.2.bak/recovery.done /var/lib/postgresql/11/main/recovery.conf
Finalmente, reinicie Postgres:
systemctl start [email protected]
La instancia secundaria ahora está de nuevo en modo de espera. Es posible que desee volver a probar la replicación en este punto.
Terminando
Elimine cualquier base de datos innecesaria en el nodo maestro, por ejemplo:
sudo -u postgres psql postgres=# DROP DATABASE replitest;
Y elimine los directorios de datos antiguos en su nodo en espera:
rm /var/lib/postgresql/11/main.bak -r rm /var/lib/postgresql/11/main.2.bak -r