基于docker容器的Postgresql 11主从复制搭建 及切换

基于docker容器的Postgresql 11主从复制搭建 及切换

1、背景

由于新项目要用到postgresql,且要求高可用功能,因此做可行性测试研究,并记录过程,以备查。
镜像采用官方postgresl11镜像,本地镜像只是为了加快部署进度.并无特殊之处。
首次应用,难免有疏漏错误之处,欢迎批评指正。

2、环境

192.168.200.153 部署主数据库

数据盘挂载在 /home目录

192.168.205.72 部署从数据库

数据盘挂载在 /data目录

3、安装部署

3.1 主服务器

利用 docker 搭建 postgres 服务器

mkdir -p  /home/postgresql/data
docker run --name test_pg --restart=always  -v /home/postgresql/data:/var/lib/postgresql/data -e POSTGRES_PASSWORD=123456 -p 5432:5432 -d 192.168.200.153:5000/test_pg:0.2

-v : 建立数据卷,将 docker 内的文件系统挂载到宿主机上, linux 目录:/home/postgresql/data, docker 容器对应的路径 /var/lib/postgresql/data

    1. 进入启动的 docker 容器内部
docker exec -it test_pg /bin/bash
    1. 进入 postgres 客户端,新建用于同步数据的用户
# 切换到 postgres 用户

su postgres

# 进去 postgres 客户端

psql

进入 postgres 客户端

CREATE ROLE replica login replication encrypted password 'replica';

注:注意语句最后添加分号
创建用户成功之后,控制台会显示 “CREATE ROLE”,利用 \du 命令可以查看 postgres 的用户列表

postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 replica   | Replication                                                | {}

查看用户列表

通过 \q 退出 postgres 控制台,并通过 exit 退出 postgres 用户

    1. 修改 pg_hba.conf 文件

修改 pg_hba.conf 文件,允许刚创建的 replica 用户从 192.168.205.72 从服务器上连接主服务器。

vi /var/lib/postgresql/data/pg_hba.conf

vi 未安装

如上显示 vi 命令没有安装,通过如下命令进行安装

apt-get update
apt-get install vim

安装成功之后,再次修改 pg_hba.conf 文件,进入最后部分,添加如下:

host   replication      replica       192.168.205.72/32          trust   #允许  205.72 机器使用 replica 用户来复制
    1. 修改 postgresql.conf
listen_addresses = '*'   # 监听所有IP
archive_mode = on  # 允许归档
archive_command = '/bin/date' # 用该命令来归档logfile segment,这里取消归档。
wal_level = replica #开启热备
max_wal_senders = 32 # 这个设置了可以最多有几个流复制连接,差不多有几个从,就设置几个
wal_keep_segments = 64 # 设置流复制保留的最多的xlog数目,一份是 16M,注意机器磁盘 16M*64 = 1G
wal_sender_timeout = 60s # 设置流复制主机发送数据的超时时间
max_connections = 200 # 这个设置要注意下,从库的max_connections必须要大于主库的
    1. 重启容器
      通过 exit 命令退出容器,并重启启动容器
docker restart test_pg

从服务器

    1. 启动从节点数据库:
mkdir -p /data/postgresql/data
docker run --name test_pg --restart=always  -v /data/postgresql/data:/var/lib/postgresql/data -e POSTGRES_PASSWORD=123456 -p 5432:5432 -d 192.168.200.153:5000/test_pg:0.2
  • 2 通过 docker exec -it test_pg /bin/bash 进入容器内部,拷贝主服务器数据进入从节点容器并同步(注意按实际情况修改master节点ip地址)
docker exec -it test_pg /bin/bash 
su postgres
rm -rf /var/lib/postgresql/data/*
pg_basebackup -h 192.168.200.153 -U replica -D /var/lib/postgresql/data -X stream -P

执行完上述命令之后,容器自动退出

切换到宿主机的 root 账户,进入 /data/postgresql/data目录。

    1. 添加 recovery.conf 文件
      通过 vi /data/postgresql/data/recovery.conf添加恢复文件 (注意按实际情况修改master节点ip地址)。
cd /data/postgresql/data

vi recovery.conf

standby_mode = on
primary_conninfo = 'host=192.168.200.153 port=5432 user=replica password=replica'
recovery_target_timeline = 'latest'
  • 4.修改 postgresql.conf

vi /data/postgresql/data/postgresql.conf

wal_level = replica
max_connections = 1000
hot_standby = on
max_standby_streaming_delay = 30s
wal_receiver_status_interval = 10s 
hot_standby_feedback = on
    1. 启动容器
      执行docker ps -a
      如果 test_pg容器已经启动
      则先执行:
docker stop test_pg

否则
通过 docker start test_pg再次启动容器

4. 校验主从部署

  • 验证方法一:
    到 192.168.200.153 主服务器地址上校验主从是否部署成功
    通过 docker exec -it test_pg /bin/bash 进入容器内部
su postgres
psql

通过上诉命令进入 postgres 控制台,然后执行:

select client_addr,sync_state from pg_stat_replication;

得到如下结果:

postgres=# select client_addr,sync_state from pg_stat_replication;
  client_addr   | sync_state 
----------------+------------
 192.168.205.72 | async
(1 row)

主从配置成功

  • 验证方法二:

主库上:

postgres@be0f0d5e17f9:/$ ps -ef | grep wal
postgres    50    28  0 14:03 ?        00:00:00 postgres: walwriter  
postgres  8760    28  0 16:04 ?        00:00:00 postgres: walsender replica 192.168.205.72(35476) streaming 0/B000060
postgres 13535 11320  0 16:44 pts/0    00:00:00 grep wal

备库上:

root@61e3c16652eb:/#  ps -ef | grep wal
postgres    51    28  0 16:01 ?        00:00:01 postgres: walreceiver  
root        91    82  0 16:44 pts/0    00:00:00 grep wal

5.测试同步状态

当然,稳妥起见,尝试在主库上创建并插入数据,观察备库上是否同步这些操作,我们再主库上创建一张表:

postgres=# create table test_ms(id int4);

CREATE TABLE

postgres=# insert into test_ms values(6);

INSERT 0 1

主库上,我们创建test_ms表,并插入了一条数据,我们就可以在备库上进行查询观察是否同步成功:

postgres=# select * from test_ms;
 id
----
 6
(1 row)

接下来,我们再主库上,再操作

postgres=# insert into test_ms values(9);
INSERT 0 1

postgres=# delete from test_ms where id=6;
DELETE 1

这个时候,我们发现备库的数据也都正常同步上了:

postgres=# select * from test_ms;
 id
----
 9
(1 row)

那么我们如果在备份上进行数据操作,情况会怎样呢?我们再备份上执行:

postgres=# insert into test_ms values(6);

ERROR: cannot execute INSERT in a read-only transaction
STATEMENT: insert into test_ms values(6);
ERROR: cannot execute INSERT in a read-only transaction

观察这些错误日志,我们可以了解到,异步流主从结构中,作为从节点的备库目前处于的是只读状态,它不能进行任何写入操作。

6. 主备切换测试

    1. 在主服务器上执行
docker stop test_pg;

关闭主库

    1. 在备库上执行pg_ctl promote命令**备库,如果recovery.conf变成recovery.done表示备库已切换成主库
docker exec -it test_pg /bin/bash 
su postgres
/usr/lib/postgresql/11/bin/pg_ctl promote -D $PGDATA promote -D $PGDATA
waiting for server to promote.... done
server promoted

命令执行后,如果原来的 recovery.conf 更名为 recovery.done, 表示切换成功

    1. 这时如果需要将老的主库切换成备库,在老的主库的$PGDATA目录下也创建recovery.conf文件(创建方式跟之前介绍的一样,内容可以和原从库pghost2的一样,只是primary_conninfo的IP换成对端pghost2的IP)

例如,主库上的 recovery.conf 设置为:

recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=192.168.205.72 port=5432 user=replica password=replica'
    1. 启动老的主库pghost1,这时观察主、备进行是否正常,严格点可以在新的主库上对刚才的test_ms表进行操作,观察数据是否同步成功。

pg_ctl start
我们在新主库(pghost2)上执行:

postgres=# select pg_is_in_recovery();
 pg_is_in_recovery
-------------------
 f
(1 row)

发现它目前的角色已经是主库了, 在新备库(pghost1)上继续执行:

postgres=# select pg_is_in_recovery();
 pg_is_in_recovery
-------------------
 t
(1 row)

发现它目前的角色也已经切换为备库了

我们再pghost2上,执行数据插入操作:

postgres=# insert into test_ms values(11);
INSERT 0 1

这时,pghost1上也观察到数据同步成功:

postgres=# select * from test_ms;
 id
----
 9
 11
(2 rows)

到这里为止,主从切换的演练基本完成了
参考文档:
https://www.codeleading.com/article/6741340817/
基于 docker 的 postgres 主从流复制部署
Postgresql主从异步流复制方案的深入探究

posted @ 2022-04-08 15:21  蒲公英PGY  阅读(923)  评论(0编辑  收藏  举报