如何在docker中使用Hot Standby设置PostgreSQL以实现高可用性和复制

0 前置条件

  • Docker
  • Postgres 镜像 (postgres版本为11

注:
关于主从ip地址的查看可以使用docker inspect 容器名来查看关于容器的网络信息 其中包含容器的ip地址
如果遇到了故障可以使用docker logs 容器名 来查看日志信息
psql中退出的命令为 \q

1 创建并配置主库

1
docker run --name pgone -d -p 5432:5432 -v ~/data/pgone:/var/lib/postgresql/data -e POSTGRES_PASSWORD=ggg postgres
  • —-name 指定名字为pgone
  • p 指定端口暴露 本机端口:容器端口
  • v 绑定宿主目录与容器文件目录 宿主文件目录:容器文件目录
  • e 指定环境变量 即指定数据库密码

    进入容器进行操作

    1
    2
    3
    4
    5
    6
    7
    8
    docker exec -it pgone bash #进入容器
    su postgres #切换到数据库对应用户
    psql #链接数据库
    CREATE TABLE guestbook (visitor_email text, vistor_id serial, date timestamp, message text); #创建一个测试用的表
    INSERT INTO guestbook (visitor_email, date, message) VALUES ( 'jim@gmail.com', current_date, 'This is a test.'); #插入一行数据
    \q #退出数据库
    createuser -U postgres repuser -P -c 5 --replication
    #创建一个新用户

createruser:

  • U 使用账户postgres创建 新用户
  • 新用户的名称是 repuser
  • P 提示输入新用户的密码
  • c 设置新用户的连接数 设置为5就够用了
  • –replication 讲 replication 的权限授予 repuser

    创建存档目录

    1
    mkdir -p /var/lib/postgresql/data/mnt/server/archivedir

编辑 pg_hba.conf

1
Vim /data/pgone/pg_hba.conf

在最后一行添加(host 为从机ip

1
host     replication     repuser         host/32        md5

编辑 postgresql.conf

1
Vim /data/pgone/postgresql.conf

WRITE AHEAD LOG部分的Settings部分中,更改WAL级别:

1
wal_level = hot_standby

Archiving部分中,更改archive mode:

1
archive_mode = on

更改archive_command的值。此设置告诉Postgres将存档文件写入您在上一步中创建的目录:

1
archive_command = 'test ! -f mnt/server/archivedir/%f && cp %p mnt/server/archivedir/%f'

REPLICATION部分的Sending Server(s)部分中,更改WAL发送方进程的最大数量的值:

1
max_wal_senders = 3

2 部署从库

从库可以将主库镜像打包成进项 然后直接生成从库容器 从而省略掉备份的过程
也可以直接使用pg_basebackup进行备份

生成并配置从库容器

1
2
3
4
docker run --name pgtwo -d -p 5433:5432 -v ~/data/pgtwo:/var/lib/postgresql/data -e POSTGRES_PASSWORD=ggg postgres
docker exce -it pgtwo bash
su postgres
pg_basebackup -h host -D /var/lib/postgresql/new_data -U repuser -v -P --xlog-method=stream #host为主库的ip地址

因为主库的备份不能直接覆盖目录 所以备份到new_data目录
主库的data目录即被备份到从库容器的
/var/lib/postgresql/new_data文件夹
随后需要将从库的data目录进行替换
可以直接修改容器的PGDATA环境变量将其指向new_data文件夹
也可以直接更换内容 我选择了一个最偷懒的方法(在容器中进行操作

1
rm -rf /var/lib/postgresql/data/* && cp /var/lib/postgresql/new_data/* /var/lib/postgresql/data/*

随后重启容器即可(这种方法并不安全 清空整个data目录后 几十秒后postgres会崩溃导致容器退出 所以要趁数据库进程不注意才可以

编辑从库postgresql.conf

1
vim /data/pgtwo/postgresql.conf

REPLICATION部分的Standby Servers部分中,打开Hot Standby并取消注释该行:

1
hot_standby = on

创建recovery 配置文件

在使用pg_basebackup的时候可以通过增加 -R参数来自动生成recover.conf文件 详情见参考文章
将示例恢复文件复制到正确的位置。在容器的终端中,输入以下命令:

1
cp -avr /usr/share/postgresql/11/recovery.conf.sample /var/lib/postgresql/data/recovery.conf

修改 recovery.conf

1
vim var/lib/postgresql/data/recovery.conf

在STANDBY SERVER PARAMETERS部分中,更改待机模式:

1
standby_mode = on

primary_conninfo 设置为主库参数

1
primary_conninfo = 'host=#主库ip# port=5432 user=repuser password=ggg'

保存后重启从库容器

测试主从复制工作情况

在主库容器中启动psql

1
2
3
4
select * from guestbook;
#查看当前表
INSERT INTO guestbook (visitor_email, date, message) VALUES ('jim@gmail.com', current_date, 'Now we are replicating.');
# 插入新行

切换至从库容器

1
2
select * from guestbook;
#查询是否成功复制

参考文章: