基于docker容器的Postgresql 11.6主从复制搭建 及切换
环境
192.168.253.70 pg1 主库
192.168.253.71 pg2 从库
安装部署
主服务器
创建数据盘
[root@pg1 ~]# mkdir -p /home/postgresql/data
运行主库容器
docker run --name pg_test --restart=always -v /home/postgresql/data:/var/lib/postgresql/data -e POSTGRES_PASSWORD=123456 -p 5432:5432 -d postgres:11.6
进入启动的 docker 容器内部
docker exec -it pg_test /bin/bash
进入 postgres 客户端,新建用于同步数据的用户
# 切换到 postgres 用户
root@e9389130297b:/# su postgres
# 进去 postgres 客户端
postgres@e9389130297b:/$ 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 用户
安装vim编辑器
root@e9389130297b:/# apt-get update
root@e9389130297b:/# apt-get install vim
修改 pg_hba.conf 文件,允许刚创建的 replica 用户从 192.168.253.71 从服务器上连接主服务器。
修改 pg_hba.conf 文件,进入最后部分,添加如下:
vi /var/lib/postgresql/data/pg_hba.con
host replication replica 192.168.253.71/32 trust #允许 253.71 机器使用 replica 用户来复制
修改 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必须要大于主库的
重启容器
docker restart pg_test
从服务器
启动从节点数据库
创建数据盘
[root@pg2 ~]# mkdir -p /data/postgresql/data
运行从库容器
docker run --name pg_test --restart=always -v /data/postgresql/data:/var/lib/postgresql/data -e POSTGRES_PASSWORD=123456 -p 5432:5432 -d postgres:11.6
通过 docker exec -it pg_test/bin/bash 进入容器内部,拷贝主服务器数据进入从节点容器并同步(注意按实际情况修改主库节点ip地址)
[root@pg2 ~]# docker exec -it pg_test bash
root@9aee344e3c8b:/# su postgres
postgres@9aee344e3c8b:/$ rm -rf /var/lib/postgresql/data/*
postgres@9aee344e3c8b:/$ pg_basebackup -h 192.168.253.70 -U replica -D /var/lib/postgresql/data -X stream -P
执行完上述命令之后,容器自动退出
切换到宿主机的 root 账户,进入 /data/postgresql/data目录。
添加 recovery.conf 文件(注意文件权限)
vim /data/postgresql/data/recovery.conf
standby_mode = on
primary_conninfo = 'host=192.168.253.70 port=5432 user=replica password=replica'
recovery_target_timeline = 'latest'
修改 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
启动容器
执行docker ps -a
如果 pg_test容器已经启动
则先停止容器再重启
[root@pg2 ~]# docker stop pg_test
[root@pg2 ~]# docker start pg_test
验证
验证方法一:
进入主库
[root@pg1 ~]# docker exec -it pg_test /bin/bash
root@e9389130297b:/# su postgres
postgres@e9389130297b:/$ psql
postgres=# select client_addr,sync_state from pg_stat_replication;
client_addr | sync_state
----------------+------------
192.168.253.71 | async
(1 row)
验证方法二:
主库上:
postgres@9aee344e3c8b:/$ ps -ef | grep wal
postgres 26 1 0 14:46 ? 00:00:00 postgres: walwriter
postgres 32 1 0 14:47 ? 00:00:00 postgres: walsender replica 192.168.253.71(57476) streaming 0/9000328
postgres 159 125 0 16:17 pts/0 00:00:00 grep wal
从库上
postgres@e9389130297b:/$ ps -ef | grep wal
postgres 27 1 0 14:47 ? 00:00:03 postgres: walreceiver streaming 0/9000328
postgres 79 67 0 16:17 pts/0 00:00:00 grep wal
测试同步状态
我们再主库上创建一张表:
postgres=# create table t1(name varchar(10));
postgres=# insert into t1 values('liu');
select * from t1;
name
----
liu
(1 row)
仓库上查看
postgres=# insert into t1 values('liu');
select * from t1;
name
----
liu
(1 row)
主备切换测试
在主服务器上执行
关闭主库
[root@pg1 ~]# docker stop pg_test
在备库上执行pg_ctl promote命令
[root@pg2 ~]# docker exec -it pg_test bash
root@9aee344e3c8b:/# su postgres
postgres@e9389130297b:/$ /usr/lib/postgresql/11/bin/pg_ctl promote -D $PGDATA
waiting for server to promote.... done
server promoted
命令执行后,如果原来的 recovery.conf 更名为 recovery.done, 表示切换成功
这时如果需要将老的主库切换成备库,在老的主库的$PGDATA目录下也创建recovery.conf文件(创建方式跟之前介绍的一样,内容可以和原从库pghost2的一样,只是primary_conninfo的IP换成对端pghost2的IP)
主库创建recovery.conf文件
recovery_target_timeline = 'latest'
standby_mode = on
primary_conninfo = 'host=192.168.253.71 port=5432 user=replica password=replica'
启动老的主库pghost1。这时观察主、备进行是否正常
我们在新主库(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)
发现它目前的角色也已经切换为备库了
注意
如果旧的主库无法与新的主库进行主从复制
需要在新的主库的pg_hba.conf =文件中添加旧的主库的ip,然后重启
如果在旧的主库中添加recovery.conf文件后,发现容器一直在启动状态,这时需要注释掉recovery_target_timeline = 'latest’这个字段,然后进行重启
如果以上两个情况都无法同步新的主库,那就需要将旧的主库的数据目录清空,重新修改配置文件并重启,操作如下
postgres@e9389130297b:~$ rm -rf /var/lib/postgresql/data/*
postgres@e9389130297b:~$ pg_basebackup -h 192.168.253.71 -U replica -D /var/lib/postgresql/data -X stream -P
修改pg_hba.conf文件,添加如下内容
host replication replica 192.168.253.70/32 trust
host replication replica 192.168.253.70/32 md5
修改postgresql.conf文件,内容修改到比新主库的值大即可
max_connections = 1000