Title

使用pg_basebackup实现简单的异步流复制

pg_basebackup实现简单的异步流复制

进行本节实验前,请先配置好docker镜像源

实验目的

了解现代数据库系统(PG)如何实现高可用性的

  1. 高可用性:主库故障时备库可快速接管服务,减少业务中断时间。
  2. 数据冗余:通过实时同步机制(WAL日志)保障数据安全,避免单点故障导致数据丢失。
  3. 负载分担:备库可承担只读查询,分担主库压力(需配置hot_standby = on)。
  4. 灾难恢复:异地部署备库可应对物理环境故障(如机房断电、网络中断)。

Docker环境下

下载Postgres的Docker Image镜像

在终端输入以下指令,下载最新的postgresql的docker镜像:

docker pull postgres

如果遇到连接超时等错误,尝试换一下docker-hub的镜像源(教程网上有)。

创建PG专属数据卷

docker volume create postgre-data

在 Docker 中,挂载数据卷(Volume Mounting)是一种非常重要的机制,用于在容器和宿主机之间或者容器与容器之间共享和持久化数据。(来源:豆包AI)

作用
1.持久化

当容器被删除时,容器内部产生的数据也会随之丢失。通过挂载数据卷,可以将数据存储在宿主机或 Docker 管理的卷中,即使容器被删除,数据仍然可以保留下来。

2. 数据共享

可以在多个容器之间共享同一个数据卷,实现容器间的数据交互。比如,一个 Web 应用容器和一个日志处理容器可以共享同一个日志数据卷,Web 应用将日志写入数据卷,日志处理容器从该数据卷读取日志进行分析。

3. 方便开发和调试

在开发过程中,可以将宿主机上的代码目录挂载到容器内部,这样在宿主机上修改代码后,容器内的代码也会同步更新,无需重新构建和启动容器,提高开发效率。

这里就是让容器内部的数据同步到宿主机,不会丢失数据。

创建并运行容器pg1(作为主库)

docker run -id --name=pg1 -v postgre-data:/var/lib/postgresql/data -p 5432:5432 -e POSTGRES_PASSWORD=123456 -e LANG=C.UTF-8 postgres

在挂载的数据卷内配置(推荐)

找到外置数据卷的文件夹位置,Ubuntu1604的文件夹位置为/var/lib/docker/volumes/postgre-data/_data

在docker外部(宿主机)执行命令(需要超级用户):

vim /var/lib/docker/volumes/postgre-data/_data/postgresql.conf

在最后加入以下配置:

wal_level = replica         # 启用WAL日志归档
max_wal_senders = 3        # 允许最多3个复制连接
hot_standby = on           # 备库可提供读服务(需重启生效)

通过命令hostname -i查看本机ip,并将本机ip加入pg_hba.conf文件:

vim /var/lib/docker/volumes/postgre-data/_data/pg_hba.conf
host replication all <your-hostname>/16 md5  # 允许Docker网络内的复制连接

直接在容器里修改配置(不推荐)

进入容器pg1,切换到用户postgres

su postgres
cd ~
cd data

编辑data文件夹下,PG的配置文件postgresql.conf,加入以下配置:

wal_level = replica         # 启用WAL日志归档
max_wal_senders = 3        # 允许最多3个复制连接
hot_standby = on           # 备库可提供读服务(需重启生效)

通过命令hostname -i查看本机ip,并将本机ip加入pg_hba.conf文件:

host replication all <your-hostname>/16 md5  # 允许Docker网络内的复制连接

更新配置

重启容器pg1

sudo docker restart pg1

或者使用pg_ctl

sudo pg_ctl restart

在容器pg1中建立新的数据库和数据表用于验证备库是否成功复制

-- 创建数据库
CREATE DATABASE student_db;

-- 连接到新创建的数据库
\c student_db;

-- 创建学生表
CREATE TABLE students (
    student_id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    age INT,
    gender CHAR(1),
    enrollment_date DATE
);

-- 插入示例数据
INSERT INTO students (name, age, gender, enrollment_date)
VALUES 
    ('张三', 20, 'M', '2024-09-01'),
    ('李四', 21, 'F', '2023-09-01'),
    ('王五', 22, 'M', '2022-09-01'),
    ('赵六', 19, 'F', '2025-01-15'),
    ('孙七', 23, 'M', '2022-03-20'),
    ('周八', 20, 'F', '2024-07-10'),
    ('吴九', 22, 'M', '2023-11-05'),
    ('郑十', 21, 'F', '2024-04-25'),
    ('王十一', 18, 'M', '2025-02-01'),
    ('李十二', 24, 'F', '2021-09-30'),
    ('张十三', 20, 'M', '2024-09-12'),
    ('刘十四', 22, 'F', '2023-06-18'),
    ('陈十五', 19, 'M', '2025-03-08');

pg2备库搭建(关键步骤)

创建备库容器(不挂载数据卷,由pg_basebackup初始化):
sudo docker run -d --name pg2 -e POSTGRES_PASSWORD=123456 postgres:latest bash -c "while true; do sleep 1; done" 

"while true; do sleep 1; done" 这部分是为了阻止容器刚开启就关闭(因为没有挂载数据卷,pg服务无法启动)。

执行 pg_basebackup
sudo docker exec -it pg2 'pg_basebackup -h <pg1的host> -U postgres -D /var/lib/postgresql/data -P -R -X stream -v'
  • -R:自动生成standby.signal文件并配置primary_conninfo
  • -X stream:实时传输未归档的WAL日志

或直接进入容器终端执行:

pg_basebackup -h <pg1的host> -U postgres -D /var/lib/postgresql/data -P -R -X stream -v
启动备库
sudo docker exec pg2 su postgres -c "pg_ctl start -D /var/lib/postgresql/data"

验证主备一致性

1. 主库检查
  • 查看复制状态

    SELECT client_addr, state, sync_state, sent_lsn, write_lsn 
    FROM pg_stat_replication;
    
    • 正常输出应包含备库IP,state = 'streaming'sync_state表示同步模式。
2. 备库检查
  • 确认恢复模式

    SELECT pg_is_in_recovery();  -- 返回`t`表示处于备库模式
    
  • 检查接收的WAL位置

    SELECT pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn();
    
    • 应与主库的sent_lsnwrite_lsn一致。
3. 数据一致性验证
  • 主库写入测试数据

    CREATE TABLE test (id SERIAL PRIMARY KEY, data TEXT);
    INSERT INTO test (data) VALUES ('HA test');
    
  • 备库查询验证

    SELECT * FROM test;  -- 应返回与主库相同数据
    
4. 日志监控
  • 主库日志:出现streaming replication successfully connected to standby
  • 备库日志:持续输出started streaming WAL from primaryconsistent recovery state

其他

一般的postgreSQL镜像不包含vim,vi,netutils等常见工具,由于镜像是Debian系统,可以使用apt安装(需要超级用户权限):

apt-get update
apt-get install <tool-name>

docker 进入容器终端

docker exec -it <container-name> bash

退出容器/用户

exit

pg_basebackup运行后,可能会文件权限错误,可以在postgres用户下执行,将权限改为750或者700

sudo chmod -R <750/700> ~/data
posted @ 2025-03-13 13:06  是胡某某啊  阅读(242)  评论(0)    收藏  举报