Docker 中 PostgreSql 主从热备,主从切换方案

环境说明

  1. Docker
  2. Windows 11
  3. PostgreSql 17

搭建步骤

0. 宿主机准备:

  1. 找个地方创建一个文件夹用来挂载容器中数据库Data文件夹,这里我用的是:
    C:\Users\Administrator\docker\Postgresql\replication

1. 主数据库准备:

  1. 执行docker run 命令,创建主数据库容器:pgsmaster
docker run --name pgsmaster -p 5400:5432 -e POSTGRES_PASSWORD=123456 -v C:\Users\Administrator\docker\Postgresql\replication\pgsmaster:/var/lib/postgresql/data -d postgres
  1. 添加复制角色用户:
# 1.进入容器 
docker exec -it pgsmaster bash 
# 2.连接PostgreSQL 
psql -U postgres 
# 3.创建用户 
// replicator: 复制账号; 123456: 认证密码 
create role replicator login replication encrypted password '123456'; 
# 4.验证用户 
\du
# 出现如下列表则用户创建成功
List of roles 
Role name  | Attributes 
-----------+-------------------------------------------
postgres   | Superuser, Create role, Create DB, Replication, Bypass RLS 
replicator | Replication
  1. 宿主机找到挂载文件夹:C:\Users\Administrator\docker\Postgresql\replication\pgsmaster 下的 postgresql.conf 文件,修改配置:

    1. listen_addresses ='*'
    2. wal_level = replica
    
  2. 找到 pg_hba.conf 文件,最后一行添加配置:

	host    replication     replicator  172.17.0.0/16       md5
  1. 重启容器:docker restart pgsmaster

到这里主数据库就准备好了~

2. 从数据库准备:

  1. 同样执行docker run 命令,创建一个从数据库容器:
docker run --name pgsslave -p 5401:5432 -e POSTGRES_PASSWORD=123456 -v C:\Users\Administrator\docker\Postgresql\replication\pgsslave:/var/lib/postgresql/data -d postgres
  1. 进入容器,进行主库复制:
	# 1. 进入容器
	docker exec -it pgsslave bash
	
	# 2. 切换postgres用户
	su postgres
	
	# 3. 清空data文件夹
	rm -rf /var/lib/postgresql/data/*
	
	# 4. 执行复制, 需要输入密码即主数据库创建复制用户replicator的密码‘123456’
	pg_basebackup -h 172.17.0.6 -U replicator -R -P -v -C --slot=pgsslave -D /var/lib/postgresql/data

[!NOTE] 命令说明:
-R 说明会创建standby.signal文件,以及补充postgresql.auto.conf的内容
-P 显示备份进度
-v 显示更加详细信息
-C 同时创建复制槽
-slot 指定复制槽的名字(一个备库一个名字)
-D 生成备库的路径

[!NOTE] 复制槽的好处:
主库的事务日志一直处于滚动消耗的状态,如果备库下线,随着主库频繁的数据变动,可能就会存在当备库重新上线后,已经找不到之前没有拉取的事务日志的情况(被主库回收掉了)。
但是有了复制槽,主库就会为复制槽保留它没有消费的日志,等待它上线后进行消费。当然代价是对磁盘的消耗,不过只要备库不是永久丢失,磁盘消耗对于大部分场景来说不是问题。
但是如果备库永久丢失了,要记得删除主库中对应的复制槽。删除复制槽的语句为 :select pg_drop_replication_slot('pgsslave');

  1. 重启容器
	docker restart pgsslave
  1. 确认是否成功, 主库执行下列查询即可
	select * from pg_replication_slots;\\查询主库中的插槽 
	select * from pg_stat_replication;\\查询已建立连接的备份库

主从切换

1. 从库切换成主库

使用以下语句将从库切换成主库

select pg_promote();

此时,从库data中的standby.signal文件已删除;并修改pg_hba.conf 文件,ip改为原主库ip

host    replication     replicator  172.17.0.0/16       md5
2. 删除原主库复制槽
select pg_drop_replication_slot('pgsslave2');
3. 将原从库的data备份到原主库

这一步是全量备份,所以要注意如果库很大,会很费时间,虽然官方文档说不会影响其他客户端,但是肯定会消耗主库的cpu,内存,磁盘I/O以及带宽;

pg_basebackup -h 172.17.0.7 -U replicator -R -P -v -C --slot=pgsslave -D /var/lib/postgresql/data

此时,主库就会变成从库,从库中也能查询到对应的备份连接

测试

1. 监控延迟

PostgreSQL 提供了一些系统视图和函数来检查复制延迟:

  • pg_stat_replication:该视图显示主数据库的流复制状态,包括从数据库的复制延迟。可以使用以下查询来查看当前的延迟:
	SELECT 
    application_name,
    client_addr,
    pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS replication_lag
    FROM pg_stat_replication;
    
    -- 其中,replication_lag 表示主数据库当前生成的 WAL 日志比从数据库已应用的日志多出多少个字节。则表示是延迟大小。
2. 主库宕机
  • 从库停止接受WAL日志,等待主库恢复。
  • 从库查询服务不受影响,可以继续接受只读查询。
  • 主库手动恢复后,从库会开始从主库接收 WAL 日志并恢复同步,恢复过程是自动的。
3. 从库宕机
  • 从库停止接受WAL日志且无法提供查询服务。
  • 主库读写正常,不受影响。
  • 从库手动恢复后,从库自动消费积压的WAL日志并与主库同步。

posted on 2024-11-28 15:48  God写注释没有代码  阅读(244)  评论(1编辑  收藏  举报

导航