基于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
-
- 进入启动的 docker 容器内部
docker exec -it test_pg /bin/bash
-
- 进入 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 用户
-
- 修改 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 用户来复制
-
- 修改 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必须要大于主库的
-
- 重启容器
通过 exit 命令退出容器,并重启启动容器
- 重启容器
docker restart test_pg
从服务器
-
- 启动从节点数据库:
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目录。
-
- 添加 recovery.conf 文件
通过 vi /data/postgresql/data/recovery.conf添加恢复文件 (注意按实际情况修改master节点ip地址)。
- 添加 recovery.conf 文件
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
-
- 启动容器
执行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. 主备切换测试
-
- 在主服务器上执行
docker stop test_pg;
关闭主库
-
- 在备库上执行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, 表示切换成功
-
- 这时如果需要将老的主库切换成备库,在老的主库的$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'
-
- 启动老的主库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主从异步流复制方案的深入探究
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了